<script>
 import { user } from '$lib/stores/user';
 import CorrectionPieChart from '$lib/components/CorrectionPieChart.svelte';
 import ListInputResponses from '$lib/components/ListInputResponses.svelte';
 import QuestionForm from '$lib/components/QuestionForm.svelte';
 import StartStopLiveSurvey from '$lib/components/StartStopLiveSurvey.svelte';
 import SurveyAdmin from '$lib/components/SurveyAdmin.svelte';
 import SurveyBadge from '$lib/components/SurveyBadge.svelte';
 import { getSurvey } from '$lib/surveys';
 import { getQuestion, getQuestions, Question } from '$lib/questions';
 import { getUsers } from '$lib/users';

 export let data;
 let survey;
 let req_questions;

 $: {
     survey = data.survey;
     updateQuestions();
     if (survey.direct !== null) {
         wsconnect();
     }
 }

 async function updateSurvey() {
     survey = await getSurvey(survey.id);
     updateQuestions();
     if (survey.direct !== null) {
         wsconnect();
     }
 }

 function updateQuestions() {
     req_questions = getQuestions(survey.id);
 }

 function deleteQuestion(question) {
     edit_question = null;
     question.delete();
 }

 let ws = null;
 let ws_up = false;
 let wsstats = null;
 let current_question = null;
 let edit_question = null;
 let responses = {};
 let corrected = false;
 let next_corrected = false;
 let with_stats = false;
 let timer = 20;
 let timer_end = null;
 let timer_remain = 0;
 let timer_cancel = null;

 function updTimer() {
     const now = new Date().getTime();
     if (now > timer_end) {
         timer_remain = 0;
         clearInterval(timer_cancel);
         timer_cancel = null;
     } else {
         timer_remain = Math.floor((timer_end - now) / 100)/10;
     }
 }

 let users = {};
 function updateUsers() {
     getUsers().then((usr) => {
         const tmp = { };
         for (const u of usr) {
             tmp[u.id.toString()] = u;
         }
         users = tmp;
     });
 }
 updateUsers();

 let scroll_states = { };
 let scroll_mean = 0;
 $: {
     let mean = 0;
     for (const k in scroll_states) {
         mean += scroll_states[k];
     }
     scroll_mean = mean / Object.keys(scroll_states).length;
 }

 let responsesbyid = { };
 $: {
     const tmp = { };
     for (const response in responses) {
         if (!tmp[response]) tmp[response] = [];
         for (const r in responses[response]) {
             tmp[response].push(responses[response][r]);
         }
     }
     responsesbyid = tmp;
 }

 let graph_data = {labels:[], datasets:[]};
 async function reset_graph_data(questionid) {
     if (questionid) {
         const labels = [];
         const flabels = [];

         let question = null;
         for (const q of await req_questions) {
             if (q.id == current_question) {
                 question = q;
             }
         }

         if (question) {
             for (const p of await question.getProposals()) {
                 flabels.push(p.id.toString());
                 labels.push(p.label);
             }
         }

         graph_data = {
             labels,
             flabels,
             datasets: [
                 {
                     values: labels.map(() => 0)
                 }
             ]
         }
     }

     if (current_question && responses[current_question] && graph_data.labels.length != 0) {
         const values = graph_data.datasets[0].values.map(() => 0);

         for (const u in responses[current_question]) {
             const res = responses[current_question][u];
             for (const r of res.split(',')) {
                 let idx = graph_data.flabels.indexOf(r);
                 values[idx] += 1;
             }
         }

         graph_data.datasets[0].values = values;
     }
 }

 let asks = [];
 function wsconnect() {
     if (ws !== null) return;

     ws = new WebSocket((window.location.protocol == 'https:'?'wss://':'ws://') + window.location.host + `/api/surveys/${data.sid}/ws-admin`);

     ws.addEventListener("open", () => {
         ws_up = true;
         ws.send('{"action":"get_responses"}');
         ws.send('{"action":"get_stats"}');
         ws.send('{"action":"get_asks"}');
     });

     ws.addEventListener("close", (e) => {
         ws_up = false;
         console.log('Socket is closed. Reconnect will be attempted in 1 second.');
         setTimeout(function() {
             ws = null;
             updateSurvey();
         }, 1500);
     });

     ws.addEventListener("error", (err) => {
         ws_up = false;
         console.log('Socket closed due to error.', err);
     });

     ws.addEventListener("message", (message) => {
         const data = JSON.parse(message.data);
         if (data.action && data.action == "new_question") {
             current_question = data.question;
             corrected = data.corrected == true;
             if (timer_cancel) {
                 clearInterval(timer_cancel);
                 timer_cancel = null;
             }
             if (data.timer) {
                 timer_end = new Date().getTime() + data.timer;
                 timer_cancel = setInterval(updTimer, 250);
             } else {
                 timer_end = null;
             }
             reset_graph_data(data.question);
         } else if (data.action && data.action == "stats") {
             wsstats = data.stats;
         } else if (data.action && data.action == "new_response") {
             if (!responses[data.question]) responses[data.question] = { };
             responses[data.question][data.user] = data.value;

             reset_graph_data();
         } else if (data.action && data.action == "new_ask") {
             asks.push({"id": data.question, "content": data.value, "userid": data.user});
             asks = asks;
         } else if (data.action && data.action == "myscroll" && wsstats && wsstats.users) {
             scroll_states[data.user] = parseFloat(data.value);
             for (const k in wsstats.users) {
                 if (wsstats.users[k].id == data.user) {
                     wsstats.users[k].myscroll = scroll_states[data.user];
                 }
             }
         } else if (data.action && data.action == "end") {
             ws.close();
             updateSurvey();
         } else {
             current_question = null;
             timer_end = null;
             if (timer_cancel) {
                 clearInterval(timer_cancel);
                 timer_cancel = null;
             }
         }
     });
 }
</script>

{#if $user && $user.is_admin}
    <StartStopLiveSurvey
        {survey}
        class="ms-1 float-end"
        on:update={() => updateSurvey()}
        on:end={() => { if (confirm("Sûr ?")) ws.send('{"action":"end"}') }}
    />
    <a href="surveys/{survey.id}/responses" class="btn btn-success ms-1 float-end" title="Voir les réponses"><i class="bi bi-files"></i></a>
{/if}
<div class="d-flex align-items-center">
    <h2>
        <a href="surveys/" class="text-muted" style="text-decoration: none">&lt;</a>
        {survey.title}
        <small class="text-muted">
            Administration
        </small>
        {#if asks.length}
            <a href="surveys/{data.sid}/admin#questions_part">
                <i class="bi bi-patch-question-fill text-danger"></i>
            </a>
        {/if}
    </h2>
    {#if survey.direct !== null}
        <div
            class="badge rounded-pill ms-2"
            class:bg-success={ws_up}
            class:bg-danger={!ws_up}
        >
            {#if ws_up}Connecté{:else}Déconnecté{/if}
        </div>
    {:else}
        <SurveyBadge
            class="mx-2"
            {survey}
        />
    {/if}
</div>

{#if survey.direct === null}
    <SurveyAdmin
        {survey}
        on:saved={updateSurvey}
    />
{:else}
    {#await req_questions}
        <div class="text-center">
            <div class="spinner-border text-primary mx-3" role="status"></div>
            <span>Chargement des questions &hellip;</span>
        </div>
    {:then questions}
        <div class="card my-3">
            <table class="table table-hover table-striped mb-0">
                <thead>
                    <tr>
                        <th>
                            Question
                            {#if timer_end}
                                <div class="input-group input-group-sm float-end" style="max-width: 150px;">
                                    <input
                                        type="number"
                                        class="form-control"
                                        disabled
                                        value={timer_remain}
                                    >
                                    <span class="input-group-text">s</span>
                                </div>
                            {:else}
                                <div class="input-group input-group-sm float-end" style="max-width: 150px;">
                                    <input
                                        type="number"
                                        class="form-control"
                                        bind:value={timer}
                                        placeholder="Valeur du timer"
                                    >
                                    <span class="input-group-text">s</span>
                                </div>
                            {/if}
                            <button
                                type="button"
                                class="btn btn-sm btn-info ms-1"
                                on:click={updateQuestions}
                                title="Rafraîchir les questions"
                            >
                                <i class="bi bi-arrow-counterclockwise"></i>
                            </button>
                        </th>
                        <th>
                            Réponses
                        </th>
                        <th>
                            <button
                                type="button"
                                class="btn btn-sm btn-primary"
                                disabled={!current_question || !ws_up}
                                on:click={() => { ws.send('{"action":"pause"}')} }
                                title="Passer sur une scène sans question"
                            >
                                <i class="bi bi-pause-fill"></i>
                            </button>
                            <button
                                type="button"
                                class="btn btn-sm"
                                class:btn-outline-success={!next_corrected}
                                class:btn-success={next_corrected}
                                on:click={() => { next_corrected = !next_corrected } }
                                title="La prochaine question est affichée corrigée"
                            >
                                <i class="bi bi-eye"></i>
                            </button>
                            <button
                                type="button"
                                class="btn btn-sm"
                                class:btn-outline-success={!with_stats}
                                class:btn-success={with_stats}
                                on:click={() => { with_stats = !with_stats } }
                                title="La prochaine correction sera affichée avec les statistiques"
                            >
                                <i class="bi bi-bar-chart-fill"></i>
                            </button>
                            <button
                                type="button"
                                class="btn btn-sm btn-outline-danger"
                                on:click={() => { fetch('api/cache', {method: 'DELETE'}) } }
                                title="Vider les caches"
                            >
                                <i class="bi bi-bandaid-fill"></i>
                            </button>
                            <button
                                type="button"
                                class="btn btn-sm btn-info mt-1"
                                on:click={() => { edit_question = new Question({ id_survey: survey.id }) } }
                                title="Ajouter une question"
                            >
                                <i class="bi bi-plus"></i>
                            </button>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    {#each questions as question (question.id)}
                        <tr>
                            <td>
                                {#if responses[question.id]}
                                    <a href="surveys/{data.sid}/admin#q{question.id}_res">
                                        {question.title}
                                    </a>
                                {:else}
                                    {question.title}
                                {/if}
                            </td>
                            <td>
                                {#if responses[question.id]}
                                    {Object.keys(responses[question.id]).length}
                                {:else}
                                    0
                                {/if}
                                {#if wsstats}/ {wsstats.nb_clients}{/if}
                            </td>
                            <td>
                                <button
                                    type="button"
                                    class="btn btn-sm"
                                    class:btn-primary={!next_corrected}
                                    class:btn-success={next_corrected}
                                    disabled={(question.id === current_question && next_corrected == corrected) || !ws_up}
                                    on:click={() => { ws.send('{"action":"new_question", "corrected": ' + next_corrected + (with_stats?', "stats": {}':'') + ', "timer": 0, "question":' + question.id + '}')} }
                                >
                                    <i class="bi bi-play-fill"></i>
                                </button>
                                <button
                                    type="button"
                                    class="btn btn-sm btn-danger"
                                    disabled={question.id === current_question || !ws_up}
                                    on:click={() => { ws.send('{"action":"new_question", "corrected": ' + next_corrected + (with_stats?', "stats": {}':'') + ', "timer": ' + timer * 1000 + ',"question":' + question.id + '}')} }
                                >
                                    <i class="bi bi-stopwatch-fill"></i>
                                </button>
                                <a
                                    href="/surveys/{survey.id}/responses/{question.id}"
                                    target="_blank"
                                    rel="noreferrer"
                                    type="button"
                                    class="btn btn-sm btn-success"
                                >
                                    <i class="bi bi-files"></i>
                                </a>
                                <button
                                    type="button"
                                    class="btn btn-sm btn-info"
                                    disabled={question.id === current_question}
                                    on:click={() => { getQuestion(question.id).then((q) => {edit_question = q})} }
                                >
                                    <i class="bi bi-pencil"></i>
                                </button>
                            </td>
                        </tr>
                    {/each}
                </tbody>
            </table>
        </div>
    {/await}
    {#if edit_question !== null}
        <QuestionForm
            {survey}
            edit
            question={edit_question}
            on:delete={() => deleteQuestion(edit_question)}
        />
    {/if}

    <hr>
    <button
        type="button"
        class="btn btn-sm btn-info ms-1 float-end"
        on:click={() => { ws.send('{"action":"get_asks", "value": ""}'); asks = []; }}
        title="Rafraîchir les réponses"
    >
        <i class="bi bi-arrow-counterclockwise"></i>
        <i class="bi bi-question-diamond"></i>
    </button>
    <button
        type="button"
        class="btn btn-sm btn-light ms-1 float-end"
        on:click={() => { ws.send('{"action":"get_asks", "value": "unanswered"}'); asks = []; }}
        title="Rafraîchir les réponses, en rapportant les réponses déjà répondues"
    >
        <i class="bi bi-arrow-counterclockwise"></i>
        <i class="bi bi-question-diamond"></i>
    </button>
    <button
        type="button"
        class="btn btn-sm btn-success float-end"
        title="Tout marqué comme répondu"
        on:click={() => { ws.send('{"action":"mark_answered", "value": "all"}'); asks = [] }}
    >
        <i class="bi bi-check-all"></i>
    </button>
    <h3 id="questions_part">
        Questions
        {#if asks.length}
            <small class="text-muted">
                {asks.length}&nbsp;question{#if asks.length > 1}s{/if}
            </small>
        {/if}
    </h3>
    {#if asks.length}
        {#each asks as ask (ask.id)}
            <div class="card mb-3">
                <div class="card-body">
                    <p class="card-text">
                        {ask.content}
                    </p>
                </div>
                <div class="card-footer">
                    <button
                        type="button"
                        class="btn btn-sm btn-success float-end"
                        title="Marqué comme répondu"
                        on:click={() => { ws.send('{"action":"mark_answered", "question": ' + ask.id + '}'); asks = asks.filter((e) => e.id != ask.id) }}
                    >
                        <i class="bi bi-check"></i>
                    </button>
                    Par
                    <a href="users/{ask.userid}" target="_blank" rel="noreferrer">
                        {#if users && users[ask.userid]}
                            {users[ask.userid].login}
                        {:else}
                            {ask.userid}
                        {/if}
                    </a>
                </div>
            </div>
        {/each}
    {:else}
        <div class="text-center text-muted">
            Pas de question pour l'instant.
        </div>
    {/if}

    <hr>
    <button
        type="button"
        class="btn btn-sm btn-info ms-1 float-end"
        on:click={() => { ws.send('{"action":"get_responses"}') }}
        title="Rafraîchir les réponses"
    >
        <i class="bi bi-arrow-counterclockwise"></i>
        <i class="bi bi-card-checklist"></i>
    </button>
    <h3>
        Réponses
    </h3>
    {#if Object.keys(responses).length}
        {#each Object.keys(responses) as q, qid (qid)}
            {#await req_questions then questions}
                {#each questions as question}
                    {#if question.id == q}
                        <h4 id="q{question.id}_res">
                            {question.title}
                        </h4>
                        {#if question.kind == 'ucq'}
                            {#await question.getProposals()}
                                <div class="text-center">
                                    <div class="spinner-border text-primary mx-3" role="status"></div>
                                    <span>Chargement des propositions &hellip;</span>
                                </div>
                            {:then proposals}
                                {#if current_question == question.id}
                                    <CorrectionPieChart
                                        {question}
                                        {proposals}
                                        data={graph_data}
                                    />
                                {:else}
                                    <CorrectionPieChart
                                        {question}
                                    />
                                {/if}
                                <div class="card mb-4">
                                    <table class="table table-sm table-striped table-hover mb-0">
                                        <tbody>
                                            {#each proposals as proposal (proposal.id)}
                                                <tr>
                                                    <td>
                                                        {proposal.label}
                                                    </td>
                                                    <td>
                                                        {responsesbyid[q].filter((e) => e == proposal.id.toString()).length}/{responsesbyid[q].length}
                                                    </td>
                                                    <td>
                                                        {Math.trunc(responsesbyid[q].filter((e) => e == proposal.id.toString()).length / responsesbyid[q].length * 1000)/10}&nbsp;%
                                                    </td>
                                                </tr>
                                            {/each}
                                        </tbody>
                                    </table>
                                </div>
                            {/await}
                {:else if question.kind == 'mcq'}
                            {#await question.getProposals()}
                                <div class="text-center">
                                    <div class="spinner-border text-primary mx-3" role="status"></div>
                                    <span>Chargement des propositions &hellip;</span>
                                </div>
                            {:then proposals}
                                {#if current_question == question.id}
                                    <CorrectionPieChart
                                        {question}
                                        {proposals}
                                        data={graph_data}
                                    />
                                {:else}
                                    <CorrectionPieChart
                                        {question}
                                    />
                                {/if}
                                <div class="card mb-4">
                                    <table class="table table-sm table-striped table-hover mb-0">
                                        <tbody>
                                            {#each proposals as proposal (proposal.id)}
                                                <tr>
                                                    <td>
                                                        {proposal.label}
                                                    </td>
                                                    <td>
                                                        {responsesbyid[q].filter((e) => e.indexOf(proposal.id.toString()) >= 0).length}/{responsesbyid[q].length}
                                                    </td>
                                                    <td>
                                                        {Math.trunc(responsesbyid[q].filter((e) => e.indexOf(proposal.id.toString()) >= 0).length / responsesbyid[q].length * 1000)/10}&nbsp;%
                                                    </td>
                                                </tr>
                                            {/each}
                                        </tbody>
                                    </table>
                                </div>
                            {/await}
                {:else if question.kind && question.kind.startsWith('list')}
                            <ListInputResponses
                                responses={responses[q]}
                                {users}
                            />
                {:else}
                            <div class="card mb-4">
                                <ul class="list-group list-group-flush">
                                    {#each Object.keys(responses[q]) as user, rid (rid)}
                                        <li class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                                            <span>
                                                {responses[q][user]}
                                            </span>
                                            <a href="users/{user}" target="_blank" rel="noreferrer" class="badge bg-dark rounded-pill">
                                                {#if users && users[user]}
                                                    {users[user].login}
                                                {:else}
                                                    {user}
                                                {/if}
                                            </a>
                                        </li>
                                    {/each}
                                </ul>
                            </div>
                        {/if}
                    {/if}
                {/each}
            {/await}
        {/each}
    {/if}

    <hr>
    <button
        type="button"
        class="btn btn-sm btn-info ms-1 float-end"
        on:click={() => { ws.send('{"action":"get_stats"}') }}
        title="Rafraîchir les stats"
    >
        <i class="bi bi-arrow-counterclockwise"></i>
        <i class="bi bi-123"></i>
    </button>
    <button
        type="button"
        class="btn btn-sm btn-primary ms-1 float-end"
        title="Rafraîchir la liste des utilisateurs"
        on:click={updateUsers}
    >
        <i class="bi bi-arrow-clockwise"></i>
        <i class="bi bi-people"></i>
    </button>
    <button
        type="button"
        class="btn btn-sm btn-warning ms-1 float-end"
        on:click={() => { scroll_states = {}; ws.send('{"action":"where_are_you"}')} }
        title="Rapporter l'avancement"
    >
        <i class="bi bi-geo-fill"></i>
    </button>
    <h3 id="users">
        Connectés
        {#if wsstats}
            <small class="text-muted">{wsstats.nb_clients} utilisateurs</small>
        {/if}
        {#if scroll_mean}
            <small
                class:text-danger={scroll_mean >= 0 && scroll_mean < 0.2}
                class:text-warning={scroll_mean >= 0.2 && scroll_mean < 0.6}
                class:text-info={scroll_mean >= 0.6 && scroll_mean < 0.9}
                class:text-success={scroll_mean >= 0.9}
            >Avancement global&nbsp;: {Math.trunc(scroll_mean*10000)/100} %</small>
        {/if}
    </h3>
    {#if wsstats && wsstats.users}
        <div class="row row-cols-5 py-3">
            {#each wsstats.users as user, lid (lid)}
                <div class="col">
                    <div class="card">
                        <img alt="{user.login}" src="//photos.cri.epita.fr/thumb/{user.login}" class="card-img-top">
                        <div class="card-footer text-center text-truncate p-0">
                            <a href="users/{user.login}" target="_blank" rel="noreferrer">
                                {user.login}
                            </a>
                        </div>
                        {#if user.myscroll != null}
                            <div
                                class="card-footer py-0 px-1"
                                class:bg-danger={user.myscroll >= 0 && user.myscroll < 0.2}
                                class:bg-warning={user.myscroll >= 0.2 && user.myscroll < 0.6}
                                class:bg-info={user.myscroll >= 0.6 && user.myscroll < 0.9}
                                class:bg-success={user.myscroll >= 0.9}
                            >
                                Avancement&nbsp;: {Math.trunc(user.myscroll*10000)/100}&nbsp;%
                            </div>
                        {/if}
                    </div>
                </div>
            {/each}
        </div>
    {/if}
{/if}
