<script lang="ts">
 import { browser } from '$app/environment';
 import { onMount } from 'svelte';
 import { base64decode } from '../../../base64';
 import { base } from '$app/paths'
 const profileModules = import.meta.glob("../../../../static/faisan/profiles/*.csv");

 export let puissance: number
 export let prms: string = ""
 export let active: string = ""
 let initialised = false
 $: {
     console.log("active", active)
     initialised && updatePlot(puissance)
 }

 let Plotly: any

 let srv = import.meta.env.MODE == 'production' ? 'coturnix.fr' : 'd.coturnix.fr'

 onMount(async () => {
     console.log("browser", browser)
     if(browser) {
         //@ts-ignore
         Plotly = await import('plotly.js-dist')
         updatePlot(puissance)
         initialised = true
     }
 })

 let prt: string[] = [
 ]

 let pr: {type:string, conso: number}[] = [
 ]

 let plotStyle = ""

 let profs: Map<string, { coefs: number[], total: number }> = new Map()

 let darkMode = false;
 if(browser) {
     darkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
     window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
         darkMode = !!event.matches
         redraw()
     });
 }

 let re = /.*\/([^\/]*)\.csv/
 for (const modulePath in profileModules) {
     console.log("module", modulePath)
     let matches = modulePath.match(re)
     console.log(matches)
     if(matches) {
         prt.push(matches[1])
     }
 }

 function addProfil(_ev: Event) {
     pr.push({ type: prt[0], conso: 0 })
     pr = pr
 }

 function delProfil(i: number) {
     pr.splice(i, 1)
     pr = pr
 }

 async function profile(name: string): Promise<{ coefs: number[], total: number }> {
     let resp = await fetch(
         `${base}/profiles/${name}.csv`,
     )
     let p = await resp.text()
     let annee = []
     let total = 0
     for(let line of p.split('\n')) {
         if(!line) {
             continue
         }
         const col = line.split(';')
         // const week = parseInt(col[0])
         // const dow = parseInt(col[1])
         const cs = parseFloat(col[2])
         const cj = parseFloat(col[3])
         for(let i = 0; i < 48; i++) {
             let ch = parseFloat(col[5+i])
             const c = cs * cj * ch
             annee.push(c)
             total += c
         }
     }
     return { coefs: annee, total }
 }

 let annee: Record<string, string[]> = {}

 async function refresh(event: SubmitEvent) {
     event.preventDefault()
     if(prms) {
         let f = new FormData()
         f.append("prms", prms);
         let resp = await fetch(
             `https://${srv}/api/faisan`,
             { method: "POST",
             body: f
             })
         if(resp.ok) {
             annee = await resp.json()
         }
     }
     if(prms || pr.length > 0) {
         await updatePlot(puissance)
     }
 }

 let auto = 0
 let totalProd = 0
 let totalConso = 0
 let soleil = {
     samples: <[Date, number][]>[],
     x: <string[]>[],
     y: <number[]>[],
     type: 'lines',
     line: {
         color:  "#ffbf00",
         width: 1,
     },
     name: "Production solaire",
     bucket: 1,
 }
 let somme = {
     samples: <[Date, number][]>[],
     x: <string[]>[],
     y: <number[]>[],
     type: 'lines',
     line: {
         color: "#b81111",
         width: 1,
     },
     name: "Consommation totale",
     bucket: 1,
 }

 async function updatePlot(puissance: number) {
     if(!browser) {
         return
     }

     soleil = {
         samples: <[Date, number][]>[],
         x: <string[]>[],
         y: <number[]>[],
         type: 'lines',
         line: {
             color:  "#ffbf00",
             width: 1,
         },
         name: "Production solaire",
         bucket: 1,
     }
     somme = {
         samples: <[Date, number][]>[],
         x: <string[]>[],
         y: <number[]>[],
         type: 'lines',
         line: {
             color: "#b81111",
             width: 1,
         },
         name: "Consommation totale",
         bucket: 1,
     }
     let min_t = 0
     let max_t = 0

     let annee_ :Record<string, { t: number[], y: number[], i: number }> = {}

     for(let [prm, r] of Object.entries(annee)) {
         let d: { t: number[], x: string[], y: number[], i: number } = {
             t: [],
             x: [],
             y: [],
             i: 0,
         }
         for(let semaine of r) {
             let b = new DataView(base64decode(semaine).buffer)
             let length = b.getUint32(0, true)
             for(let i = 8; i < 8 + 8 * length; i+= 8) {
                 let t = b.getUint32(i, true)
                 let v = b.getUint32(i+4, true)

                 if(!min_t || t < min_t) {
                     min_t = t
                 }
                 if(t > max_t) {
                     max_t = t
                 }

                 d.t.push(t)
                 d.y.push(v)
             }
         }
         annee_[prm] = d
     }

     if(pr.length > 0) {
         if(min_t >= max_t) {
             let d = new Date()
             min_t = (new Date(d.getFullYear(), 0, 1)).getTime() / 1000
             max_t = min_t + 364 * 24 * 3600
         }

         for (let p of pr) {
             let d: { t: number[], y: number[], i: number } = {
                 t: [],
                 y: [],
                 i: 1,
             }
             let i = 0
             for(let t = min_t; t <= max_t; t += 1800) {
                 d.t.push(t);
                 let pp = profs.get(p.type)
                 if(!pp) {
                     profs.set(p.type, await profile(p.type))
                 }
                 if(pp) {
                     d.y.push(1000 * pp.coefs[i] * p.conso / pp.total)
                 }
                 i += 1
             }
             annee_[p.type] = d
         }
     }

     auto = 0
     totalProd = 0
     totalConso = 0

     let annuelle = await fetch("https://coturnix.fr/pvgis")
     let pvgis: {outputs: { hourly: {time: string, "G(i)": number, T2m: number, H_sun: number, Int: number}[]}} = await annuelle.json()
     const start = new Date(min_t * 1000)
     const janvier = new Date(start.getFullYear(), 0, 1)
     for(let t = min_t; t < max_t; t += 1800) {
         let tt = new Date(t*1000);
         let len = pvgis.outputs.hourly.length
         let n = ((t * 1000 - janvier.getTime()) / 3600000) % len
         let pp = 0

         if(n == Math.floor(n)) {
             pp = pvgis.outputs.hourly[n].H_sun
         } else {
             let extra = n - Math.floor(n)
             pp = pvgis.outputs.hourly[Math.floor(n)]['G(i)'] * (1 - extra)
                + pvgis.outputs.hourly[Math.floor(n) + 1]['G(i)'] * extra
         }
         soleil.samples.push([
             tt,
             pp * puissance
         ])
         let y = 0
         for(let [_, r] of Object.entries(annee_)) {
             while(r.i + 1 < r.t.length && r.t[r.i + 1] < t) {
                 r.i += 1
             }
             if(r.i < r.t.length) {
                 if(!isNaN(r.y[r.i]))
                     y += r.y[r.i]
             }
         }
         somme.samples.push([
             tt,
             y
         ])
         totalProd += pp * puissance
         totalConso += y
         auto += Math.min(y, pp * puissance)
     }

     console.log(totalProd, totalConso);
     if(!Plotly)
         //@ts-ignore
         Plotly = await import('plotly.js-dist')

     if(max_t > min_t) {
         redraw()
     }
 }

 function sample(
     s: { samples: [Date, number][], x: string[], y: number[], bucket: number },
     w?: number,
 ) {
     console.log("sample", w, s);
     let ww = w || s.samples.length
     let n = 400
     let bbox = (<SVGGraphicsElement | undefined>(document.getElementsByClassName("bglayer")[0]))?.getBBox()
     if(bbox && bbox.width >= 200) {
         n = bbox.width / 2
     }
     s.bucket = Math.ceil(ww / n)
     console.log("bucket", s.bucket);
     s.x = [];
     s.y = [];
     for(let i = 0; i < s.samples.length; ) {
         const i0 = i;
         let sum = 0;
         let sz = Math.min(s.bucket, s.samples.length - i0)
         for(; i < i0 + s.bucket && i < s.samples.length; i++) {
             sum += s.samples[i][1] / sz
         }
         s.x.push(s.samples[i0][0].toLocaleString())
         s.y.push(sum)
     }
 }

 function redraw() {
     sample(soleil)
     sample(somme)
     let layout = {
         title: "Autoconsommation",
         autosize: true,
         automargin: true,
         plot_bgcolor: "#fff0",
         paper_bgcolor: "#fff0",
         font: {
             color: darkMode ? '#fff': '#000'
         },
         xaxis: {
             gridcolor: darkMode ? '#444': '#bbb',
             ticklabeloverflow: 'allow',
             ticklabelstep: 4,
         },
         yaxis: {
             title: { text: 'kW' },
             gridcolor: darkMode ? '#444': '#bbb',
             color: darkMode ? '#fff': '#000',
         },
     }
     plotStyle = "min-height:450px"
     Plotly!.react('plot', [soleil, somme], layout, { responsive: true });

     let relayout = function(event: any) {
         console.log(event)
         let w = event["xaxis.range[1]"] - event["xaxis.range[0]"]
         let layout_ = JSON.parse(JSON.stringify(layout))
         if(isNaN(w)) {
             sample(soleil)
             sample(somme)
             console.log(layout_)
             layout_.xaxis.autorange = true
             layout_.yaxis.autorange = true
             plotStyle = "min-height:450px"
             Plotly!.react('plot', [soleil, somme], layout_, { responsive: true })
         } else {
             let sb = somme.bucket
             sample(soleil, w)
             sample(somme, w)
             let sb_ = somme.bucket
             console.log("buckets", sb, sb_)
             layout_.xaxis.range = [
                 event["xaxis.range[0]"] * sb / sb_,
                 event["xaxis.range[1]"] * sb / sb_,
             ]
             layout_.yaxis.autorange = true
             /*range = [
                event["yaxis.range[0]"],
                event["yaxis.range[1]"],
                ]*/
             console.log(layout_.xaxis)
             plotStyle = "min-height:450px"
             Plotly!.react('plot', [soleil, somme], layout_, { responsive: true })
         }
     };
     //@ts-ignore
     document.getElementById('plot')?.on('plotly_relayout', relayout)

     var dataProd = [{
         values: [Math.round(auto), Math.round(totalProd - auto)],
         labels: ['Autoconsommé', 'Surplus'],
         marker: { colors: ["#ffbf00dd", "#b81111dd"] },
         type: 'pie',
         sort: false,
         hole: .5,
     }];

     var dataConso = [{
         values: [Math.round(auto), Math.round(totalConso - auto)],
         labels: ['Autoproduit', 'Alloproduit'],
         marker: { colors: ["#ffbf00dd", "#b81111dd"] },
         type: 'pie',
         sort: false,
         hole: .5,
     }];

     plotStyle = "min-height:450px"
     Plotly.react('autoProd', dataProd, {
         title: "Autoconsommation",
         font: {
             color: darkMode ? '#fff': '#000'
         },
         plot_bgcolor: "#fff0",
         paper_bgcolor: "#fff0",
         autosize: true,
         legend: {
             orientation: "h",
         }
     }, { responsive: true });
     Plotly.react('autoConso', dataConso, {
         title: "Autoproduction",
         font: {
             color: darkMode ? '#fff': '#000'
         },
         plot_bgcolor: "#fff0",
         paper_bgcolor: "#fff0",
         autosize: true,
         legend: {
             orientation: "h",
         }
     }, { responsive: true });
 }
</script>
<form method="POST" action="/api/faisan" id="pdl" on:submit={refresh}>
</form>
<table class="table">
    {#each pr as pr, i}
        <tr>
            <td class="px-3">Profil</td>
            <td>
                <select class="form-select" bind:value={pr.type}>
                    {#each prt as p}
                        <option value={p}>{p}</option>
                    {/each}
                </select>
            </td>
            <td>
                <input type="number" class="form-control" placeholder="Consommation Annuelle (kWh)" bind:value={pr.conso}/>
            </td>
            <td style="width:1%;white-space:nowrap;">
                <button class="btn btn-primary" on:click={(_ev) => delProfil(i)}><i class="bi bi-x-circle"/></button>
            </td>
        </tr>
    {/each}
    <tr>
        <td class="px-3" style="width: 25%">Liste de PDL, séparés par des virgules</td>
        <td colspan="3"><input class="form-control" form="pdl" id="prms" name="prms" bind:value={prms}/></td>
    </tr>
</table>

<div class="my-5 text-center">
    <button class="btn btn-primary" on:click={addProfil}><i class="bi bi-plus-circle" /> Ajouter un profil</button>

    <button class="btn btn-primary" form="pdl">Simuler</button>
</div>
<div class="my-3">
    <div class="mx-auto" style={plotStyle} id="plot"></div>
</div>
<div class="my-3 row">
    <div class="col-12 col-sm-6 p-0" style={plotStyle} id="autoConso"></div>
    <div class="col-12 col-sm-6 p-0" style={plotStyle} id="autoProd"></div>
</div>