import TransactionStatus from "./TransactionStatus.js";

export default class TransactionPhase {
    /**
     * ################################
     * TRANSACTION PHASE TRANSITIONS
     * ################################
     * 
     * 1. INITIAL
     *      -> CANCELED  (transaction was cancled before any api calls were done)
     *      -> BUY_IN_PROGRESS  (transaction was send to api with buy order)
     * 
     * 2. BUY_IN_PROGRESS
     *      -> CANCELED  (transaction was canceled before any coins were bought)
     *      -> BUY_DONE  (buy order was partially or fully fullfilled)
     * 
     * 3. BUY_DONE
     *      -> SELL_IN_PROGRESS  (sell order was performed on api)
     * 
     * 4. SELL_IN_PROGRESS
     *      -> BUY_DONE  (sell order was cancled before coins were fully sold)
     *      -> SELL_DONE  (sell order was fully fullfilled but transaction is not closed yet)
     * 
     * 5. SELL_DONE
     *      -> FINISHED  (transaction was closed)
     * 
     * 6. FINISHED (final state)
     * 
     * 7. CANCELED (final state)
     */


    /**
     * Start state of each transaction. It was created but not propagated to the api.
     * @type {string}
     */
    static INITIAL = "INITIAL";

    /**
     * State 'Canceled' will indicate, that this transaction was finished with 0 coins bought and 0 coins sold.
     * If a buy order is cancled before it was even partialy filled the whole transaction will be marked as canceled.
     * @type {string}
     */
    static CANCELED = "CANCELED";

    /**
     * State 'Finished' will be set, if buy and sell of this transaction are done.
     * Cancaling a transaction after it is partialy done will result in a 'Finished' state too.
     * Every transaction should end with a 'Finished' or 'Canceled' state.
     * @type {string}
     */
    static FINISHED = "FINISHED"

    /**
     * The buy order was placed at the market place and is waiting for fill.
     * Canceling a transaction in this state will result in FINISHED or CANCELED depending on
     * partial / full fill of this order
     * @type {string}
     */
    static BUY_IN_PROGRESS = 'BUY_IN_PROGRESS';

    /**
     * The sell order was placed at the market place and is waiting for fill.
     * Canceling a transaction in this state will result in BUY_DONE state so the 
     * transaction will remain open
     * @type {string}
     */
    static SELL_IN_PROGRESS = 'SELL_IN_PROGRESS';

    /**
     * The buy order was executed an more then 0 coins were bought.
     * A transaction in this state can not be cancled anymore. It can only by closed 
     * by selling the coins
     * @type {string}
     */
    static BUY_DONE = 'BUY_DONE';

    /**
     * The sell order was executed.
     * This state is only temporarly until the transaction is finished.
     * @type {string}
     */
    static SELL_DONE = 'SELL_DONE';

    static PHASE_TRANSFER_ARRAY = [
        TransactionPhase.INITIAL,
        TransactionPhase.BUY_IN_PROGRESS,
        TransactionPhase.BUY_DONE,
        TransactionPhase.SELL_IN_PROGRESS,
        TransactionPhase.SELL_DONE,
        TransactionPhase.FINISHED
    ];

    /**
     * @param {string} phase 
     * @returns {boolean}
     */
    static isBuyPhase(phase){
        return this.BUY_IN_PROGRESS === phase
            || this.BUY_DONE === phase;
    }

    /**
     * @param {string} phase 
     * @returns {boolean}
     */
    static isSellPhase(phase){
        return this.SELL_IN_PROGRESS === phase
            || this.SELL_DONE === phase;
    }

    /**
     * @param {string} phase 
     * @returns {boolean}
     */
    static isFinalPhase(phase){
        return phase === this.CANCELED 
            || phase === this.FINISHED;
    }

    /**
     * @param {status} currentPhase see TransactionPhase
     * @param {string} status see TransactionStatus
     * @param {boolean} hasFills 
     * @returns {string}
     */
    static getPhaseForStatus(currentPhase, status, hasFills){
        if(this.isFinalPhase(currentPhase)){
            return phase;
        }

        if(this.isBuyPhase(currentPhase)){
            if(TransactionStatus.isCancled(status) && !hasFills){
                return this.CANCELED;
            }

            if((TransactionStatus.FILLED == status) || (TransactionStatus.isCancled(status) && hasFills)){
                return this.BUY_DONE;
            }
        }

        if(this.isSellPhase(currentPhase)){
            if(TransactionStatus.isCancled(status)){
                return this.BUY_DONE;
            }

            if(TransactionStatus.FILLED == status){
                return this.FINISHED;
            }
        }

        return phase;
    }
}