import {useStore} from "@/store/store.js";

// disable debug messages logging
let console = { log: function() {} }

const file_res =      ['1m', '3m', '5m', '10m', '15m', '30m', '1H', '2H', '4H', '8H', '12H', '1D', '2D', '3D', '1W',];
const supported_res = ['1', '3', '5', '10', '15', '30', '60', '120', '240', '480', '720', '1D', '2D', '3D', '1W',];

const resMap = {}
for (const i in file_res) {
    resMap[supported_res[i]] = file_res[i]
}

export function tvResolutionToPeriodString(res) {
    return resMap[res]
}

export async function jBars (symbol, contract, from, to, res) {
    console.log('[jBars]: Method call', res, from, to, symbol, contract);

    const toDate = new Date(to*1000);
    const fromDate = new Date(from*1000);
    if (res==="1W") { // for 1W, day must be Sunday
        const day = fromDate.getUTCDay(); // 0<=day<7
        fromDate.setDate(fromDate.getDate() + (7-day)%7 );
    }

    // Set fromDate to be compatible with Tim's datafiles.
    // This potentially increases number of samples returned.
    
    if (res.endsWith("W") || res.endsWith("D")) { // Days/Weeks -- set to midnight
        fromDate.setUTCHours(0, 0, 0);
    } else {
        let minutesRes = parseInt(res);
        if (minutesRes >= 60) { // Hours
            let hoursRes = Math.floor(minutesRes/60);
            let fromHours = fromDate.getUTCHours();
            fromDate.setUTCHours(fromHours - fromHours % hoursRes, 0, 0, 0);
        } else { // Minutes
            let fromMinutes = fromDate.getUTCMinutes();
            fromDate.setUTCMinutes(fromMinutes - fromMinutes % minutesRes, 0, 0);
        }
    }

    console.log("fromDate:", fromDate.toUTCString());
    console.log("toDate:  ", toDate.toUTCString());

    // contract = "0xC31E54c7a869B9FcBEcc14363CF510d1c41fa443";
    // contract = "0xC6962004f452bE9203591991D15f6b388e09E8D0";

    const daily_res     = ['1', '3', '5', '10', '15', '30'];
    const single_res    = ['1W'];

    if (!supported_res.includes(res)) throw Error(`resolution ${res} not supported.`);

    const is_daily_res  = daily_res.includes(res);
    const is_single_res = single_res.includes(res);
    const is_monthly_res = !is_single_res && !is_daily_res;

    let bars = [];
    let inverted;

    for ( // Once around for each sample in from-to range
        let iDate = fromDate,
            // loop state
            iFile = undefined,
            iohlc = 0,
            ohlc;
        iDate < toDate;
        ) {

        let bar = undefined;

        // Fetch one sample file as needed
    
        if (iFile === undefined ? true :
            is_monthly_res ? iFile.getUTCMonth() !== iDate.getUTCMonth() :
            is_daily_res   ? iFile.getUTCDate()  !== iDate.getUTCDate() :
            false // is_single_res
            ) {

            const fres = tvResolutionToPeriodString(res)
            const yr = iDate.getUTCFullYear();
            const yrdir = is_single_res ? "" : `/${yr}`;
            const mo = String(iDate.getUTCMonth()+1).padStart(2, '0'); // January is month 0 in Date object
            const date = is_daily_res ? String(iDate.getUTCDate()).padStart(2, '0') : "";
            const yrmo = !is_single_res ? `-${yr}${mo}` : "";
            let baseURL = "https://alpha.dexorder.trade/ohlc/"

            let chainId = useStore().chainId

            inverted = symbol.inverted
            if (symbol.x?.data) {
                baseURL = symbol.x.data.uri
                chainId = symbol.x.data.chain
                contract = symbol.x.data.symbol
                inverted ^= symbol.x.data.inverted
            }

            let url = `${baseURL}${chainId}/${contract}/${fres}${yrdir}/${contract}-${fres}${yrmo}${date}.json`;

            let response = await fetch(url);
            if (response.ok) {
                ohlc = await response.json();
                // todo handle inversion
                console.log(`Fetch: ${ohlc.length} resolution ${res} samples from ${url}`)
                console.log(`first: ${new Date(ohlc[0][0]*1000).toUTCString()}`)
                console.log(`last:  ${new Date(ohlc[ohlc.length-1][0]*1000).toUTCString()}`)
            } else {
                console.log(`Fetch: file not found: ${url}`)
                ohlc = []; // no file, then empty data
            }
            iFile = new Date(iDate);
            iohlc  = 0;
        }

        // Skip samples not for our time

        for(; iohlc < ohlc.length; iohlc++ ) {
            // if ( new Date(ohlc[iohlc][0]+'Z').getTime() >= iDate.getTime() ) break;
            if ( ohlc[iohlc][0]*1000 >= iDate.getTime() ) break;
        }

        let ohlcDate = iohlc >= ohlc.length ? undefined : new Date(ohlc[iohlc][0]*1000);

        // no ohlc sample file, or sample file exists and asking for sample beyond last sample, insert missing sample

        const insert_missing_samples = false;
        const visible_missing_samples = false;
        if (ohlcDate === undefined) {
            bar = {
                time:  iDate.getTime(),
            }
            if (visible_missing_samples) bar = Object.assign(bar, {
                        // Comment these to make invisible
                        open:  50,
                        high:  50,
                        low:   0,
                        close: 0,
            });
            if (!insert_missing_samples) bar = undefined;
        }
        
        // file exists, but ohlc sample not for this time, insert missing sample
        else if ( iDate.getTime() !== ohlcDate.getTime() ) {
            bar = {
                time:  iDate.getTime(),
            }
            if (visible_missing_samples) bar = Object.assign(bar, {
                open:  100,
                high:  100,
                low:   0,
                close: 0,
            });
            if (!insert_missing_samples) bar = undefined;
        } 

        // Copy ohlc sample
        else {
            bar = {
                time:  iDate.getTime(),
                open:  ohlc[iohlc][1] ?? ohlc[iohlc][4], // open
                high:  ohlc[iohlc][2] ?? ohlc[iohlc][4], // high
                low:   ohlc[iohlc][3] ?? ohlc[iohlc][4], // low
                close: ohlc[iohlc][4], // close
            }
            iohlc++;
        }

        if (bar !== undefined) {
            if (inverted) {
                bar.open = 1/bar.open
                let high = bar.high
                bar.high = 1/bar.low
                bar.low = 1/high
                bar.close = 1/bar.close
            }
            bars.push(bar);
        }

        // Increment loop variable

        if (supported_res.indexOf(res)<supported_res.indexOf('1D')) { // <1day
            const mins = parseInt(res);
            iDate.setUTCMinutes(iDate.getUTCMinutes()+mins)
        } else if (res==='1W') { // 1W
            iDate.setUTCDate(iDate.getUTCDate()+7); 
        } else { // <1W >1day
            iDate.setUTCDate(iDate.getUTCDate()+1); 
        } 
    }

    // noData should be set only if no bars are in the requested period and earlier.
    // In our case, we are guaranteed to have contiguous samples.
    // So we only return no bars (bars.length==0) if:
    // 1. period is entirely before first data available.
    // 2. period is entirely after last data available.
    // Returning noData based on bars.length works perfectly assuming that TV never asks for case 2.
    // This is probably not a safe assumption. The alternative would be to search
    // backward to find beginning of history. How far to search?

    let noData = bars.length === 0;
    if (noData) console.log("noData == true!");
    return [bars, {noData}];
}
