<script lang="ts">
    import { browser } from '$app/environment'
    import { onMount, tick } from 'svelte'
    import { dev } from '$app/environment';
    import { assets as a } from '$app/paths'
    import type { Writable }from 'svelte/store'
    import { get }from 'svelte/store'
    import { getContext } from 'svelte'
    import { Grain } from '../../../../grain-types'
    import { base } from '$app/paths'
    import { chooseScale, relayout, modeBarButtonsToRemove } from '../../../../plot'
    import type { Sample } from '../../../../plot'
    import type {Derived, PVGIS, PVGISInputs} from '../calcul'
    import * as calcul from '../calcul'

    export let data: {
        id: string,
        accesParticuliers: boolean,
        prms: Grain.Prm[],
        active: boolean,
        profils: Grain.Profil[],
    };

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

    console.log(data)

    export let assets: string = a;

    let s: Derived = getContext("simulation")
    const soleil: Writable<Sample> = getContext("soleil")
    const expert: Writable<boolean> = getContext("expert")
    let _communaute: Writable<(Grain.Communaute & {isMoving?: boolean}) | null> = getContext("communaute")

    const server = dev ? 'http://localhost:5173' : 'https://coturnix.fr'

    function addPrm(_ev: Event) {
        data.prms.push({ prm: null, nom: '', prenom: '', siret: '', pro: true })
        data.prms = data.prms
    }

    const pvgis: Writable<{ pvgis: null | PVGIS, loading: boolean }> = getContext("pvgis")
    let pvgis_: null | PVGISInputs = null

    export let pvgis_loading = false
    let prm_loading = false

    let initialised = false

    let puissance = 0
    let communaute: null | (Grain.Communaute & { isMoving?: boolean }) = null

    let Plotly: any

    let erreur = ''


    onMount(async () => {
        //@ts-ignore
        Plotly = await import('plotly.js-dist')
        s.p.puissance.subscribe((value) => {
            puissance = value
            initialised && updatePlot(puissance, communaute)
        })
        _communaute.subscribe((value) => {
            communaute = value
            initialised && updatePlot(puissance, communaute)
        })
        pvgis.subscribe((pvgis) => {
            console.log("pvgis updated")
            if(initialised && (pvgis.pvgis?.inputs != pvgis_)) {
                pvgis_ = pvgis.pvgis?.inputs || null
                updatePlot(puissance, communaute)
            }
        })
        for(let p of data.prms) {
            p.consentement = false
        }
        initialised = true
        updatePlot(puissance, communaute)
    })


    let plotStyle = ''

    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 profils_ = Grain.profils($expert)
    expert.subscribe((value) => profils_ = Grain.profils(value))

    function addProfil(_ev: Event) {
        const prt = Object.keys(profils_)
        data.profils.push({ type: prt[0], conso: 0 })
        data.profils = data.profils
    }

    async function delProfil(i: number) {
        data.profils.splice(i, 1)
        data.profils = data.profils
        await updatePlot(puissance, communaute)
    }

    const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

    var lastRequest = performance.now()

    async function refresh(event: SubmitEvent) {
        event.preventDefault()
        if (data.prms) {
            prm_loading = true
            await tick()
            for(let i = 0; i < data.prms.length; i++) {
                var file = document.getElementById(`releve-${i}`) as HTMLInputElement | null;
                if (file?.files?.length) {
                    var reader = new FileReader();
                    reader.readAsText(file.files[0], "UTF-8");
                    let r: string | undefined = await new Promise((resolve) => {
                        reader.onload = function (evt) {
                            console.log(typeof (evt.target?.result))
                            let result = evt.target?.result?.toString()
                            if(result) {
                                resolve(result)
                            } else {
                                resolve(undefined)
                            }
                        }
                    })
                    data.prms[i].releve = r
                }
                let siret = document.getElementById(`siret-${i}`) as HTMLInputElement | null;
                if(siret?.value) {
                    let now = performance.now();
                    // Rate-limiting: pas plus de 7 requêtes par seconde.
                    if(now - lastRequest < 150) {
                        await sleep(150 - (now - lastRequest))
                    }
                    lastRequest = now
                    const resp = await fetch(
                        `https://recherche-entreprises.api.gouv.fr/search?q=${siret.value}`
                    )
                    if(resp.status == 200) {
                        type Ent = {
                            results: {
                                dirigeants: {
                                    nom: string,
                                    prenoms: string,
                                }[],
                                matching_etablissements: {
                                    libelle_voie: string,
                                    commune: string,
                                }[]
                            }[]
                        }
                        let ent: Ent = await resp.json()
                        console.log(ent.results[0].matching_etablissements[0].commune)
                        if(ent.results.length) {
                            data.prms[i].nom = ent.results[0].dirigeants[0].nom
                            data.prms[i].prenom = ent.results[0].dirigeants[0].prenoms
                            data.prms[i].codeinsee = ent.results[0].matching_etablissements[0].commune
                            console.log(data.prms[i])
                        }
                    }
                }
            }
            console.log(data.prms);
            const resp = await fetch(
                `${server}/api/grain/projet/${data.id || 'nouveau'}/prms`,
                {
                    method: 'POST',
                    body: JSON.stringify(data.prms),
                }
            )
            if (resp.ok) {
                annee = await resp.json()
            }
            prm_loading = false
            await tick()
        } else {
            erreur = 'La liste des PRMs est vide'
        }
        await updatePlot(puissance, communaute)
    }

    let auto = 0
    let totalProd = 0
    let totalConso = 0

    let somme: Sample = {
        hourly: {
            x: [],
            y: [],
        },
        daily: {
            x: [],
            y: [],
        },
        weekly: {
            x: [],
            y: [],
        },
        x: [],
        y: [],
        type: 'bar',
        line: {
            color: '#b81111',
            width: 1,
        },
        marker: {
            color: '#b81111',
            width: 1,
        },
        name: 'Consommation totale',
        bucket: 1,
    }

    async function updatePv(
        puissance: number,
        communaute: (Grain.Communaute&{isMoving?: boolean}) | null,
    ) {
        if(communaute?.isMoving) {
            return pvgis
        }
        pvgis_loading = true
        await calcul.updatePv(puissance, communaute, pvgis, soleil, base)
        pvgis_loading = false
        await tick()
    }


    async function updatePlot(
        puissance: number,
        communaute: (Grain.Communaute & { isMoving?: boolean }) | null,
    ) {
        console.log("isMoving", communaute?.isMoving)
        if(communaute?.isMoving) {
            return
        }
        if (!browser) {
            return
        }

        await updatePv(puissance, communaute)
        console.log("updated")
        prm_loading = true;
        let auto_ = await calcul.updatePlot(
            assets,
            annee,
            data.profils,
            profils_,
            somme,
            soleil,
        )
        prm_loading = false;
        auto = auto_.auto
        totalProd = auto_.totalProd
        totalConso = auto_.totalConso
        console.log("updated auto", auto, totalProd, totalConso)
        if (!Plotly)
            //@ts-ignore
            Plotly = await import('plotly.js-dist')

        redraw()
    }

    let has_plot = { has_plot: false };
    let layout = {};

    function relayout_(event: any) {
        console.log('relayout_')
        const plot = document.getElementById('plot')!
        relayout(event, plot, Plotly, layout, has_plot, get(soleil), somme)
    }

    function redraw() {
        console.log("redraw")
        const plot = document.getElementById('plot')
        if (!plot) return
        let soleil_ = get(soleil)
        chooseScale(soleil_)
        chooseScale(somme)
        let unite: string
        if (soleil_.bucket == 24) {
            unite = 'kWh/jour'
        } else if (soleil_.bucket == 24 * 7) {
            unite = 'kWh/semaine'
        } else {
            unite = 'kWh'
        }
        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,
                tickangle: 45,
                tickformat: soleil_.bucket < 24 ? '%x %X': '%x',
                type: 'datetime',
            },
            yaxis: {
                title: { text: unite },
                gridcolor: darkMode ? '#444' : '#bbb',
                color: darkMode ? '#fff' : '#000',
            },
            showlegend: true,
            legend: {
                xanchor: 'center',
                x: 0.5,
                y: -0.4,
                orientation: 'h',
            },
        }

        if (has_plot.has_plot) {
            Plotly!.update(plot, [soleil_, somme], layout)
        } else {
            Plotly!.newPlot(plot, [soleil_, somme], layout, {
                responsive: true,
                modeBarButtonsToRemove: modeBarButtonsToRemove,
            })
            //@ts-ignore
            plot.on('plotly_relayout', relayout_)
            has_plot.has_plot = true
        }

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

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

        if(totalProd && totalConso) {
            plotStyle = 'min-height:450px'
            Plotly.react(
                'autoProd',
                dataProd,
                {
                    title: "Autoconsommation sur l'année",
                    font: {
                        color: darkMode ? '#fff' : '#000',
                    },
                    plot_bgcolor: '#fff0',
                    paper_bgcolor: '#fff0',
                    autosize: true,
                    automargin: true,
                    legend: {
                        orientation: 'h',
                    },
                },
                { responsive: true }
            )
            Plotly.react(
                'autoConso',
                dataConso,
                {
                    title: "Autoproduction sur l'année",
                    font: {
                        color: darkMode ? '#fff' : '#000',
                    },
                    plot_bgcolor: '#fff0',
                    paper_bgcolor: '#fff0',
                    autosize: true,
                    automargin: true,
                    legend: {
                        orientation: 'h',
                    },
                },
                { responsive: true }
            )
        } else {
            plotStyle = ''
        }
    }
</script>
<div class="tab-content" id="simuTabContent">
    <div
        class="tab-pane fade active show p-3"
        id="simu-tab-pane"
        role="tabpanel"
        aria-labelledby="simu-tab"
        tabindex="0">
        <h3 class="my-3 fs-1 fw-bold">Production… <span class="text-primary">Consommation</span></h3>

        <form method="POST" action="/api/grain" id="pdl" on:submit={refresh} />
        {#if erreur}
            <div
                id="erreur"
                class="alert alert-danger fade d-flex"
                class:show={erreur}
                role="alert">
                {erreur}
                <button
                    type="button"
                    class="btn-close"
                    style="padding:20px;margin:-16px -16px -16px auto"
                    on:click={() => (erreur = '')}
                    aria-label="Close" />
            </div>
        {/if}
        <h2 class="my-5">Profils de consommation</h2>
        {#if data.profils.length}
            {#if $expert}
                <div>Vous êtes en mode expert. Dans ce mode, vous avez un accès direct à tous les profils utilisés par les opérateurs du réseau pour simuler les consommations. Voir <a href="https://www.enedis.fr/responsable-dequilibre-profilage-et-profils">la documentation</a>.</div>
            {/if}
            <table class="table">
                <thead
                ><tr><th /><th>Profil</th><th>Consommation annuelle (kWh)</th><th /></tr
                                                                                    ></thead>
                <tbody>
                    {#each data.profils as pr, i}
                        <tr>
                            <td class="px-3 align-middle">Profil</td>
                            <td>
                                <select
                                    class="form-select"
                                    bind:value={pr.type}
                                    on:change={(_ev) =>
                                                  updatePlot(
                                                      puissance,
                                                      communaute,
                                                  )}>
                                    {#each Object.entries(profils_) as [p, _]}
                                        <option value={p}>{p}</option>
                                    {/each}
                                </select>
                            </td>
                            <td>
                                <input
                                    type="number"
                                    class="form-control"
                                    placeholder="Abonnement (kW)"
                                    min="0"
                                    step="500"
                                    bind:value={pr.conso}
                                    on:change={(_ev) =>
                                                  updatePlot(
                                                      puissance,
                                                      communaute,
                                                  )} />
                            </td>
                            <td style="width:1%;white-space:nowrap;text-align:center">
                                <button
                                    class="btn btn-link"
                                    on:click={(_ev) => delProfil(i)}
                                    ><i class="bi bi-x-circle text-primary" /></button>
                            </td>
                        </tr>
                    {/each}
                </tbody>
            </table>
        {/if}
        <div class="text-center">
            <button class="btn btn-primary" on:click={addProfil}
            ><i class="bi bi-plus-circle" />&nbsp;Ajouter un profil</button>
        </div>

        <h2 class="my-5">Relevés de compteurs</h2>
        {#if data.active && data.id && data.id != 'nouveau'}
            <div class="mb-5">Vous pouvez ajouter des compteurs d'entreprises ou d'associations par leur numéro de compteur et leur numéro de SIRET.
            </div>
            {#if data.prms.length}
                {#each data.prms as prm, i}

                    <div class="row my-2">
                        <div class="col-3 d-flex align-middle">
                            <label class="ms-auto form-label" for="prm-{i}">PRM<button
                                                                                   type="button"
                                                                                   class="btn btn-link align-baseline p-0 ms-2"
                                                                                   data-bs-toggle="popover"
                                                                                   data-bs-trigger="hover focus"
                                                                                   data-bs-content="Un PRM, aussi appelé PDL, est l'identifiant d'un compteur électrique. On peut le trouver sur les factures d'électricité, ou en appuyant sur le bouton + du compteur Linky."><i class="bi bi-question-circle" /></button>
                            </label>
                        </div>
                        <div class="col d-flex align-items-center">
                            <input
                                class="form-control form-control-sm"
                                id="prm-{i}"
                                bind:value={prm.prm}
                                on:keydown={(e) => (e.key == 'ArrowUp' || e.key == 'ArrowDown') && e.preventDefault() }
                                type="number" />
                        </div>
                        <div class="col col-auto d-flex align-items-center">
                            <button
                                class="btn btn-outline-primary btn-sm"
                                on:click={(e) => { e.preventDefault(); data.prms.splice(i, 1); data.prms = data.prms; }}
                                ><i class="bi bi-trash"/></button>
                        </div>
                    </div>
                    <div class="row my-2">
                        <div class="col-3 d-flex align-middle">
                            <label class="ms-auto form-label" for="prm-{i}">Relevé au format CSV</label>
                        </div>
                        <div class="col d-flex align-items-center">
                            <input
                                class="form-control form-control-sm"
                                id="releve-{i}"
                                type="file" />
                            {#if prm.releve?.length}
                                <i class="ms-3 bi bi-check-circle"/>
                            {/if}
                        </div>
                    </div>
                    <div class="row my-2">
                        <div class="col-9 ms-auto">
                            <input type="radio" class="btn-check" id="particulier" value={false} bind:group={prm.pro}>
                            <label class="btn btn-sm" for="particulier">Particulier</label>

                            <input type="radio" class="btn-check" id="pro" value={true} bind:group={prm.pro}>
                            <label class="btn btn-sm" for="pro">Professionnel</label>
                        </div>
                    </div>
                    {#if prm.pro}
                        <div class="row my-2">
                            <div class="col-3 d-flex text-end align-items-center">
                                <label class="ms-auto form-label" for="siret-{i}">SIRET du titulaire du compteur</label>
                            </div>
                            <div class="col-9 d-flex align-items-center">
                                <input
                                    class="form-control form-control-sm"
                                    id="siret-{i}"
                                    bind:value={prm.siret} />
                            </div>
                        </div>
                        <div class="row my-2">
                            <div class="col-3 d-flex text-end align-items-center">
                                <label class="ms-auto form-label" for="prenom-{i}">Prénom du titulaire du compteur</label>
                            </div>
                            <div class="col-9 d-flex align-items-center">
                                <input
                                    class="form-control form-control-sm"
                                    id="prenom-{i}"
                                    bind:value={prm.prenom}
                                    />
                            </div>
                        </div>
                        <div class="row my-2">
                            <div class="col-3 d-flex text-end align-items-center">
                                <label class="ms-auto form-label" for="nom-{i}">Nom du titulaire du compteur</label>
                            </div>
                            <div class="col-9 d-flex align-items-center">
                                <input
                                    class="form-control form-control-sm"
                                    id="nom-{i}"
                                    bind:value={prm.nom}
                                    />
                            </div>
                        </div>
                    {:else}
                        <div class="row my-2">
                            <div class="col-3 d-flex text-end align-items-center">
                                <label class="ms-auto form-label" for="prenom-{i}">Prénom du titulaire du compteur</label>
                            </div>
                            <div class="col-9 d-flex align-items-center">
                                <input
                                    class="form-control form-control-sm"
                                    id="prenom-{i}"
                                    bind:value={prm.prenom} />
                            </div>
                        </div>
                        <div class="row my-2">
                            <div class="col-3 d-flex text-end align-items-center">
                                <label class="ms-auto form-label" for="nom-{i}">Nom du titulaire du compteur</label>
                            </div>
                            <div class="col-9 d-flex align-items-center">
                                <input
                                    class="form-control form-control-sm"
                                    id="nom-{i}"
                                    bind:value={prm.nom} />
                            </div>
                        </div>
                        <div class="row my-2">
                            <div class="col-3 d-flex text-end align-items-center">
                                <label class="ms-auto form-label" for="numerorue-{i}">Numéro et rue</label>
                            </div>
                            <div class="col-9 d-flex align-items-center">
                                <input
                                    class="form-control form-control-sm"
                                    id="numerorue-{i}"
                                    bind:value={prm.numerorue} />
                            </div>
                        </div>
                        <div class="row my-2">
                            <div class="col-3 d-flex text-end align-items-center">
                                <label class="ms-auto form-label" for="codepostal-{i}">Code INSEE de la commune</label>
                            </div>
                            <div class="col-9 d-flex align-items-center">
                                <input
                                    class="form-control form-control-sm"
                                    id="codepostal-{i}"
                                    bind:value={prm.codeinsee} />
                            </div>
                        </div>
                        <div class="row my-2">
                            <div class="col-3 d-flex text-end align-items-center">
                                <label class="ms-auto form-label" for="serie-{i}">Numéro de série</label>
                            </div>
                            <div class="col-9 d-flex align-items-center">
                                <input
                                    class="form-control form-control-sm"
                                    id="serie-{i}"
                                    bind:value={prm.serie} />
                            </div>
                        </div>
                    {/if}
                    <div class="my-3 form-check d-flex">
                        <input
                            class="form-check-input ms-auto me-2"
                            type="checkbox"
                            id="consentement-{i}"
                            bind:checked={prm.consentement} />
                        <label class="form-check-label me-auto" for="consentement-{i}">Cet abonné consent à ce que j'accède à ses données.</label>
                    </div>
                    <hr class="my-4" />
                {/each}
            <div class="my-3">
                Ce service ne consulte la courbe de charge du compteur communiquant qu'une seule fois, et ce consentement expire dès que ces données pour l'année écoulée sont récupérées. Les données collectées depuis les compteurs communiquants sont stockées temporairement sur nos serveurs pour des raisons de performance, ne sont utilisées que pour afficher cette page et produire le rapport, et ne sont jamais conservées plus de 30 jours.
            </div>
            <div class="my-3">
                Les données envoyées via un fichier sont conservées jusqu'à ce que vous supprimiez ce projet.
            </div>
            {/if}
            <div class="d-flex justify-content-center">
                <button class="mx-2 btn btn-primary" on:click={addPrm}><i class="bi bi-plus-circle" />&nbsp;Ajouter un compteur</button>
                {#if data.prms.length}
                    <button
                        disabled={!!data.prms.find((p) => !p.releve?.length && !p.consentement)}
                        class="mx-2 btn btn-primary"
                        form="pdl">Mettre à jour</button>
                    <div
                        class="mx-2 spinner-border text-primary"
                        class:d-none={!prm_loading} />
                {/if}
            </div>
        {:else if data.active}
            <div class="my-3">
                Sauvegardez ce projet pour avoir accès aux relevés de compteurs détaillés.
            </div>
        {:else}
            <div class="my-3">
                Vous devez être abonné pour avoir accès aux relevés de compteurs détaillés.
            </div>
        {/if}
        <h2 class="mt-5">Simulation</h2>
        <table class="table table-bordered d-inline-block">
            <tbody>
                <tr><td>Production totale:</td><td>{Math.round(totalProd)}kWh</td></tr>
                <tr
                ><td>Consommation totale:</td><td>{Math.round(totalConso)}kWh</td
                                                                             ></tr>
            </tbody>
        </table>
        {#if pvgis_loading}
            <div class="my-3 d-flex align-items-center text-primary">
                <div class="spinner-border text-primary me-3" />
                Chargement de la production solaire
            </div>
        {/if}

        <div class="my-3">
            <div class="mx-auto" style="min-height:450px" id="plot" />
        </div>
        <div class="row">
            <div class="col-12 col-sm-6 p-0" style={plotStyle} id="autoProd" />
            <div class="col-12 col-sm-6 p-0" style={plotStyle} id="autoConso" />
        </div>
    </div>
</div>
<style>
    input::-webkit-outer-spin-button,
    input::-webkit-inner-spin-button {
        -webkit-appearance: none;
        margin: 0;
    }
    input[type=number] {
        appearance: none;
        -moz-appearance:textfield; /* Firefox */
    }
</style>