import TradingPair from "../../../apiwrapper/assets/TradingPair.js";
import KLineEvent from "../../../apiwrapper/event/KLineEvent.js";
import OrderBookUpdateEvent from "../../../apiwrapper/event/OrderBookUpdateEvent.js";
import Ticker24hEvent from "../../../apiwrapper/event/Ticker24hEvent.js";
import OrderBook from "../../../apiwrapper/orderbook/OrderBook.js";
import OrderBookEntry from "../../../apiwrapper/orderbook/OrderBookEntry.js";
import AssetDataCollectionConfig from "./AssetDataCollectionConfig.js";
import PeakDetector from "./PeakDetector.js";
import TimedAssetData from "./TimedAssetData.js";

export default class AssetData extends TimedAssetData {
    /**
     * @type {TradingPair}
     */
    #tradingPair = null;

    /**
     * @type {AssetDataCollectionConfig}
     */
    #config = null;

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

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

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

    /**
    * @type {OrderBookEntry} 
     */
    #bestBid24h = 0;

    /**
    * @type {OrderBookEntry} 
     */
    #bestAsk24h = 0;

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

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

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

    /**
     * @type {OrderBook}
     */
    #orderBook = new OrderBook();

    /**
     * @type {PeakDetector}
     */
    #peakDetector = new PeakDetector();

    /**
     * @param {TradingPair} tradingPair 
     * @param {AssetDataCollectionConfig} collectionConfig 
     */
    constructor(tradingPair, collectionConfig) {
        super([31536000000, ...collectionConfig.getTimePeriodsInMs()]);
        this.#tradingPair = tradingPair;
        this.open();
    }

    /**
     * @param {Ticker24hEvent} tickerEvent 
     */
    update24hData(tickerEvent) {
        this.#priceChange24h = tickerEvent.priceChange;
        this.#priceChangePercent24h = tickerEvent.priceChangePercent;
        this.#weightedAveragePrice24h = tickerEvent.weightedAveragePrice;
        this.#bestBid24h = new OrderBookEntry(tickerEvent.bestBidPrice, tickerEvent.bestBidQuantity);
        this.#bestAsk24h= new OrderBookEntry(tickerEvent.bestAskPrice, tickerEvent.bestAskQuantity);
        this.#high24h = tickerEvent.height;
        this.#low24h = tickerEvent.low;
        this.#trades24h = tickerEvent.trades;
    }

    /**
     * @param {KLineEvent} klineEvent 
     */
    updateKline(klineEvent) {
        this.push(klineEvent.high, klineEvent.low, klineEvent.open, klineEvent.close);
    }

    /**
     * @param {OrderBookUpdateEvent} orderBookUpdateEvent 
     */
    updateOrderBook(orderBookUpdateEvent){
        this.#orderBook.update(orderBookUpdateEvent);
        this.pushBestBid(this.#orderBook.getBestBid());
        this.pushBestAsk(this.#orderBook.getBestAsk());
        this.#peakDetector.push(this.#orderBook.getBestAsk());
    }

    /**
     * @returns {OrderBook}
     */
    getOrderBook(){
        return this.#orderBook;
    }

    /**
     * @param {string} chronoTimeString 
     * @returns {number}
     */
    getPeakCountInTimeslot(chronoTimeString){
        return this.#peakDetector.getPeakCountInTimeSlot(chronoTimeString);
    }

    /**
     * @returns {PeakDetector}
     */
    getPeakDetector(){
        return this.#peakDetector;
    }

    /**
     * @returns {TradingPair}
     */
    getTradingPair(){
        return this.#tradingPair;
    }

    /**
     * @returns {number}
     */
    get24hLow(){
        return this.#low24h;
    }

    /**
     * @returns {number}
     */
    get24hHigh(){
        return this.#high24h;
    }

    /**
     * @returns {number}
     */
    get24hPriceChange(){
        return this.#priceChange24h;
    }

    /**
     * @returns {number}
     */
    get24hPriceChangePercent(){
        return this.#priceChangePercent24h;
    }

    /**
     * @returns {number}
     */
    get24hTrades(){
        return this.#trades24h;
    }

    /**
     * @param {number} high 
     * @param {number} low 
     * @param {number} open 
     * @param {number} close 
     */
    push(high, low, open, close) {
        super.push(high, low, open, close);
        const slots = this.getSubData();
        for(let i = slots.length - 2; i >= 0; i--){
            slots[i].removeSubData();
        }
    }
}