import Transaction from "../../apiwrapper/transaction/Transaction.js";
import AbstractStrategy from "./AbstractStrategy.js";
import AvgMinMaxStrategy from "./AvgMinMaxStrategy.js";
import PossiblePeakStrategy from "./PossiblePeakStrategy.js";
import Simple24hStrategy from "./Simple24hStrategy.js";

export default class TestStrategy extends AbstractStrategy {

    /**
     * @type {AbstractStrategy[]}
     */
    #strategies = [];

    /**
     * @type {Map<string, number>}
     */
    #transactionToStrategyMap = new Map();

    /**
     * @type {number}
     */
    #lastBuyStrategyIndex = -1;

    constructor(){
        super();
        this.#strategies.push(new Simple24hStrategy());
        this.#strategies.push(new PossiblePeakStrategy());
        this.#strategies.push(new AvgMinMaxStrategy());
    }

    /**
     * @param {Logger} logger 
     */
    init(logger){
        super.init(logger);
        this.#strategies.forEach(s => s.init(logger));
    }

    /**
     * @param {Transaction} transaction 
     * @returns {boolean}
     */
    shouldSell(transaction) {
        if(!this.#transactionToStrategyMap.has(transaction.id)){
            return false;
        }

        if(this.#strategies[this.#transactionToStrategyMap.get(transaction.id)].shouldSell(transaction)){
            const winPercent = (this.getAssetData().getOrderBook().getBestBid().price / transaction.buySettings.price) * 100 - 100;
            this.getLogger().info("[TestStrategy][SELL] Strategy " + this.#strategies[this.#transactionToStrategyMap.get(transaction.id)].constructor.name + " fullfilled order with a win of " + winPercent +"%");
            this.#transactionToStrategyMap.delete(transaction.id);
            return true;
        }

        return false;
    }

    /**
     * @returns {boolean}
     */
    shouldBuy() {
        for(let i = 0; i < this.#strategies.length; i++){
            if(this.#strategies[i].shouldBuy()){
                this.#lastBuyStrategyIndex = i;
                this.getLogger().info("[TestStrategy][BUY] Strategy " + this.#strategies[i].constructor.name + " placed order!");
                return true;
            }
        }
    }

    /**
     * @param {AssetData} assetData 
     */
    setAssetData(assetData) {
        super.setAssetData(assetData);
        this.#strategies.forEach(s => s.setAssetData(assetData));
    }

    /**
     * @param {Transaction} transaction 
     */
    addTransaction(transaction){
        if(this.#lastBuyStrategyIndex >= 0){
            this.#transactionToStrategyMap.set(transaction.id, this.#lastBuyStrategyIndex);
            this.#lastBuyStrategyIndex = -1;
        }
    }

    /**
     * @param {Transaction} transaction 
     * @returns {boolean}
     */
    shouldCancle(transaction) {
        return false;
    }

    /**
    * @returns {string} string representation of this object
    */
    toJson() {
        const obj = JSON.parse(super.toJson());

        return JSON.stringify(obj);
    }

    /**
     * @param {string} objString 
     * @returns {TestStrategy}
     */
    static fromJson(objString) {
        return new TestStrategy();
    }
}