import OrderBookEntry from "../../../apiwrapper/orderbook/OrderBookEntry.js";
import UnitHelper from "../../util/UnitHelper.js";
import PeakPoint from "./PeakPoint.js";

export default class PeakDetector {
    /**
     * @type {number}
     */
    maxPeaksToStore = 100;

    /**
     * @type {number}
     */
    minPeakValueInPercent = 1.5;

    /**
     * @type {PeakPoint[]}
     */
    peaks = [];

    /**
     * @type {number}
     */
    #min = 0;

    /**
     * @type {number}
     */
    #minTime = 0;

    /**
     * @type {number}
     */
    #max = 0;

    /**
     * @type {number}
     */
    #maxTime = 0;

    /**
     * @param {OrderBookEntry} entry 
     */
    push(entry){
        if(this.#maxTime == 0){
            this.#resetPeakDetection(entry);
            return;
        }

        if(this.#min > entry.price){
            this.#min = entry.price;
            this.#minTime = Date.now();
        }

        if(this.#max < entry.price || this.#minTime >= this.#maxTime){
            this.#max = entry.price;
            this.#maxTime = Date.now();
        }
        
        if((this.#minTime < this.#maxTime || this.#max == entry.price) && this.#min * this.minPeakValueInPercent / 100 <= this.#max - this.#min){
            const peak = new PeakPoint();
            peak.startTime = this.#minTime;
            peak.startValue = this.#min;
            peak.endTime = this.#maxTime;
            peak.endValue = this.#max;
            this.peaks.push(peak);

            console.log("Peak detected [" + peak.startValue + " - " + peak.endValue + "]: " + peak.getPeakSizeInPercent() + "%");
            while(this.peaks.length > this.maxPeaksToStore){
                this.peaks.shift();
            }

            this.#resetPeakDetection(entry);
        }
    }

    /**
     * @param {string} chronoTimeString 
     * @returns {number}
     */
    getPeakCountInTimeSlot(chronoTimeString){
        const startTime = Date.now() - UnitHelper.formatedDurationToMs(chronoTimeString);
        let peaks = 0;

        for(let i = this.peaks.length - 1; i >= 0; i--){
            if(this.peaks[i].startTime >= startTime){
                peaks++;
            }
        }

        return peaks;
    }

    /**
     * @param {number} start timestamp
     * @param {number} end timestamp
     * @returns {PeakPoint[]}
     */
    getPeaksStartingBetween(start, end){
        const result = [];

        this.peaks.forEach(p => {
            if(p.startTime >= start && p.startTime <= end){
                result.push(p);
            }
        });

        return result;
    }

    /**
     * @param {number} start timestamp
     * @param {number} end timestamp
     * @returns {PeakPoint[]}
     */
    getPeaksEndingBetween(start, end){
        const result = [];

        this.peaks.forEach(p => {
            if(p.endTime >= start && p.endTime <= end){
                result.push(p);
            }
        });

        return result;
    }

    /**
     * @param {OrderBookEntry} entry 
     */
    #resetPeakDetection(entry){
        this.#min = this.#max  = entry.price;
        this.#minTime = this.#maxTime = Date.now();
    }

    toString(){
        return "[" + this.#min + " (" + this.#minTime + ") - " + this.#max + " (" + this.#maxTime + ")] (" + this.peaks.length + ")";
    }
}