// Les "any" sont un peu essentiels ici pour des raisons de Plotly.
/* eslint-disable @typescript-eslint/no-explicit-any */
export type Annee = Record<string, { t: number[]; y: number[]; i: number }>

export type Sample = {
    hourly: { x: Date[]; y: number[] }
    daily: { x: Date[]; y: number[] }
    weekly: { x: Date[]; y: number[] }
    x: Date[]
    y: number[]
    type: string
    line: {
        color: string
        width: number
    }
    marker: {
        color: string
        width: number
    }
    name: string
    bucket: number
}

export const modeBarButtonsToRemove = [
    'pan2d',
    'lasso2d',
    'toImage',
    'autoscale2d',
    'select2d',
    'zoomIn2d',
    'zoomOut2d',
]

export function sample(
    min_t: number,
    max_t: number,
    annee: Annee,
    somme: Sample,
    soleil: Sample
): { auto: number; totalProd: number; totalConso: number }
export function sample(
    min_t: number,
    max_t: number,
    annee: Annee,
    somme: Sample
): undefined
export function sample(
    min_t: number,
    max_t: number,
    annee: Annee,
    somme: Sample,
    soleil?: Sample
): undefined | { auto: number; totalProd: number; totalConso: number } {
    let auto = 0
    let totalProd = 0
    let totalConso = 0

    somme.hourly = { x: [], y: [] }
    somme.daily = { x: [], y: [] }
    somme.weekly = { x: [], y: [] }

    let i = 0
    for (const r of Object.values(annee)) {
        r.i = 0
    }
    for (let t = min_t; t < max_t; t += 3600) {
        const tt = new Date(t * 1000)
        let y = 0
        for (const r of Object.values(annee)) {
            // Les profils Enedis sont échantillonnés à la
            // demi-heure, il faut ajouter deux points consécutifs
            while (r.i < r.t.length && r.t[r.i] < t + 3600) {
                if (!isNaN(r.y[r.i])) y += r.y[r.i]
                r.i += 1
            }
        }
        somme.hourly.x.push(tt)
        somme.hourly.y.push(y)
        if ((t - min_t) % (24 * 3600) == 0) {
            if ((t - min_t) % (24 * 7 * 3600) == 0) {
                somme.weekly.x.push(tt)
                somme.weekly.y.push(y)
            } else {
                somme.weekly.y[somme.weekly.y.length - 1] += y
            }
            somme.daily.x.push(tt)
            somme.daily.y.push(y)
        } else {
            somme.daily.y[somme.daily.y.length - 1] += y
            somme.weekly.y[somme.weekly.y.length - 1] += y
        }
        totalConso += y
        if (soleil) {
            totalProd += soleil.hourly.y[i]
            auto += Math.min(y, soleil.hourly.y[i])
        }
        i += 1
    }
    if (soleil) {
        return {
            auto,
            totalProd,
            totalConso,
        }
    }
}

export type PlotSample = {
    x: Date[]
    y: number[]
    bucket: number
}

export function chooseScale(elt: Element, s: Sample & PlotSample, w?: number) {
    console.log('chooseScale', w)
    // ww: nombre d'échantillons bruts à afficher
    const ww = w || s.hourly.x.length
    const bbox = (<SVGGraphicsElement | undefined>(
        elt.getElementsByClassName('bglayer')[0]
    ))?.getBBox()
    console.log('chooseScale', elt.getElementsByClassName('bglayer'), bbox)
    const width = (bbox?.width || 100) / 3
    if (ww <= width) {
        s.x = s.hourly.x
        s.y = s.hourly.y
        s.bucket = 1
    } else if (ww / 24 <= width) {
        s.x = s.daily.x
        s.y = s.daily.y
        s.bucket = 24
    } else {
        s.x = s.weekly.x
        s.y = s.weekly.y
        s.bucket = 24 * 7
    }
}

export function relayout(
    event: any,
    plot: HTMLElement,
    Plotly: any,
    layout: any,
    has_plot: { has_plot: boolean },
    r: {
        prod?: Sample & PlotSample
        conso?: Sample & PlotSample
        reserve?: Sample & PlotSample
    }
) {
    if (event.bucket) {
        console.log('bucket, false')
        return false
    }
    const x0 = Date.parse(event['xaxis.range[0]']) / 1000
    const x1 = Date.parse(event['xaxis.range[1]']) / 1000

    const w = x1 - Math.max(0, x0)
    const layout_ = JSON.parse(JSON.stringify(layout))
    if (!plot) {
        console.log('!plot, false')
        return false
    }
    console.log('test', w)
    if (isNaN(w)) {
        if (r.prod) chooseScale(plot, r.prod)
        if (r.conso) chooseScale(plot, r.conso)
        if (r.reserve) chooseScale(plot, r.reserve)
        layout_.xaxis.autorange = true
        layout_.yaxis.autorange = true
        event.bucket = r.conso?.bucket || r.prod?.bucket || 1
    } else {
        if (r.prod) chooseScale(plot, r.prod, w / 3600)
        if (r.conso) chooseScale(plot, r.conso, w / 3600)
        if (r.reserve) chooseScale(plot, r.reserve, w / 3600)
        console.log('CHOOSE', r.prod, r.conso, r.reserve)
        event.bucket = r.conso?.bucket || r.prod?.bucket || 1
        let unite: string
        if (event.bucket == 24) {
            unite = 'kWh/jour'
        } else if (event.bucket == 24 * 7) {
            unite = 'kWh/semaine'
        } else {
            unite = 'kWh'
        }
        layout_.yaxis.title.text = unite
        layout_.yaxis.autorange = true
        layout_.yaxis.fixedrange = false
        layout_.xaxis.autorange = false
        layout_.xaxis.range = [x0 * 1000, x1 * 1000]
    }

    const pl = []
    if (r.conso) {
        pl.push(r.conso)
    }
    if (r.reserve) {
        pl.push(r.reserve)
    }
    if (r.prod) {
        pl.push(r.prod)
    }

    if (has_plot.has_plot) {
        Plotly!.update(plot, pl, layout_)
    } else {
        Plotly!.newPlot(plot, pl, layout_, {
            responsive: true,
            modeBarButtonsToRemove: modeBarButtonsToRemove,
            displaylogo: false,
            displayModeBar: true,
        })
        ;(plot as any).on('plotly_relayout', (event: any) =>
            relayout(event, plot, Plotly, layout, has_plot, r)
        )
        has_plot.has_plot = true
    }
}
