<script>
    import { onMount } from 'svelte';
    import { useTinyRouter } from 'svelte-tiny-router';
    import { api }     from '../../urls.svelte.js';
    import { t }       from '../../translations.svelte.js';
    import { display } from '../../time.svelte.js';

    import TimeEditor from '../../Components/TimeRecordEditor.svelte';

    let docLinks = $state(null);
    let error = $state(null);
    let router = useTinyRouter();
    let times = $state(null);
    let tasks = {};
    let projects = {};
    let detail = $state(null);
    let sortedTimes = $derived.by(() => Object.values(times).map(time => ({
      ...time,
      start: display(time.start_time),
      end: display(time.end_time),
      end_date: display(time.end_time)?.substring(0,10)
    })).sort((b, a) => a.start_time - b.start_time));
    let selected = $state({});
    let ranges = {};
    let timeMap = $derived.by(calcYearMap);
    let selectionSum = $derived(sortedTimes.filter(time => selected[time.id]).map(time => time.duration).reduce((acc, a) => acc + a, 0));

    function calcYearMap(){
        let result = {
            months : {},
            years  : {}
        }
        let lastYear   = null;
        let lastMonth  = null;
        let yearCount  = 0;
        let monthCount = 0;
        let yearIndex  = 0;
        let monthIndex = 0;
        for (let idx in sortedTimes){
            const time  = sortedTimes[idx];
            const year  = time.start.substring(0,4);
            const month = time.start.substring(5,7);
            if (year != lastYear){
                lastYear = year;
                if (yearCount) result.years[yearIndex] = yearCount;
                yearCount = 0;
                yearIndex = idx;
            }
            yearCount +=1;
            if (month != lastMonth){
                lastMonth = month;
                if (monthCount) result.months[monthIndex] = monthCount;
                monthCount = 0;
                monthIndex = idx;
            }
            monthCount +=1;
        }
        if (yearCount)  result.years[yearIndex] = yearCount;
        if (monthCount) result.months[monthIndex] = monthCount;
        return result;
    }

    async function joinTimes(evt, id1, id2){
        evt.preventDefault();
        evt.stopPropagation();
        const url = api('time/join');
        const res = await fetch(url,{
            credentials : 'include',
            method      : 'POST',
            body        : `${id1}+${id2}`
        });
        if (res.ok){
            error = null;
            let json = await res.json();
            delete times[id1];
            delete times[id2];
            times[json.id] = json;
        } else {
            error = await res.text();
        }
        return false;
    }

    async function loadTimes(){
        const url  = api('time');
        const resp = await fetch(url,{credentials:'include'});
        if (resp.ok){
            var json = await resp.json();
            times    = json.times;
            tasks    = json.tasks;
            projects = json.projects;
            docLinks = json.documents;
        } else {
            error = await resp.text();
        }
    }

    function onAbort(){
        detail = null;
    }

    function onclick(e){
        e.preventDefault();
        let href = e.target.getAttribute('href');
        if (href) router.navigate(href);
        return false;
    }


    async function onDrop(time_id){
        const url = api(`time/${time_id}`);
        const res = await fetch(url,{
            credentials:'include',
            method:'DELETE'
        });
        if (res.ok){
            delete times[time_id];
            error = false;
        } else {
            error = await res.text();
        }
    }

    function openProject(pid){
        router.navigate(`/project/${pid}/view`);
    }

    function openTask(tid){
        router.navigate(`/task/${tid}/view`);
    }

    function toggleRange(range){
        let affected = sortedTimes.filter(time => time.start.startsWith(range));
        if (ranges[range]){
            delete ranges[range];
            for (let time of affected){
                if (selected[time.id]) delete selected[time.id]
            }
        } else {
            for (let time of affected) selected[time.id] = true;
            ranges[range] = true;
        }
    }

    function toggleSelect(time_id){
        detail = null;
        if (selected[time_id]) {
            delete selected[time_id]
        } else selected[time_id] = true;
    }

    async function update(time){
        const url = api(`time/${time.id}`);
        const res = await fetch(url,{
            credentials:'include',
            method:'PATCH',
            body:JSON.stringify(time)
        });
        if (res.ok){
            let json = await res.json();
            let id = json.id;
            for (let key of Object.keys(json)) times[id][key] = json[key];
            detail = null;
            error = null;
            return true;
        } else {
            error = await res.text();
            return false;
        }
    }

    onMount(loadTimes);
</script>

<svelte:head>
    <title>Umbrella – {t('timetracking')}</title>
</svelte:head>

<h1>{t('timetracking')}</h1>
{#if error}
<span class="error">{error}</span>
{/if}
{#if times}
{#if selectionSum}
<div class="timetracks sum">
    {t('sum_of_records')}: <span>{selectionSum.toFixed(3)}&nbsp;{t('hours')}</span>
</div>
{/if}
<table class="timetracks">
    <thead>
        <tr>
            <th>{t('year')}</th>
            <th>{t('month')}</th>
            <th>{t('start')}<wbr>…<wbr>{t('end')}</th>
            <th>{t('duration')}</th>
            <th>{t('subject')}</th>
            <th>{t('projects')} / {t('tasks')}</th>
            <th>{t('state')}</th>
        </tr>
    </thead>
    <tbody>
        {#each sortedTimes as time,line}
        <tr class={selected[time.id]?'selected':''}>
            {#if timeMap.years[line]}
            <td class="year" rowspan={timeMap.years[line]} onclick={e => toggleRange(time.start.substring(0,4))}>
                {time.start.substring(0,4)}
            </td>
            {/if}
            {#if timeMap.months[line]}
            <td class="month" rowspan={timeMap.months[line]} onclick={e => toggleRange(time.start.substring(0,7))}>
                {time.start.substring(5,7)}
            </td>
            {/if}
            {#if detail == time.id}
            <td colspan="5">
                <TimeEditor record={time} {onAbort} {onDrop} onSet={update} />
            </td>
            {:else}
            <td class="start_end" onclick={e => toggleSelect(time.id)}>
                {time.start}{#if time.end_time}<wbr>…<wbr>{time.start.startsWith(time.end_date)?time.end.substring(11):time.end}{/if}
                {#if line>0 && Math.abs(sortedTimes[line-1].start_time - time.end_time)<100}
                <button class="symbol join" title={t('join_objects',{objects:t('times')})} onclick={e => joinTimes(e, time.id, sortedTimes[line-1].id)} ></button>
                {/if}
            </td>
            <td class="duration" onclick={e => {detail = time.id}}>
                {#if time.duration}
                {time.duration.toFixed(3)}&nbsp;h
                {/if}
            </td>
            <td class="subject" onclick={e => {detail = time.id}}>
                {time.subject}
            </td>
            <td class="tasks" onclick={e => {detail = time.id}}>
            <ul>
                {#each time.task_ids as tid}
                {#if tasks[tid]}
                <li>
                    {#if tasks[tid] && projects[tasks[tid].project_id]}
                    <a href="/project/{tasks[tid].project_id}/view" {onclick}>{projects[tasks[tid].project_id].name}</a> /
                    {/if}
                    <a href="/task/{tid}/view" {onclick}>{tasks[tid].name}</a>
                </li>
                {/if}
                {/each}
            </ul>
            </td>
            <td class="state" onclick={e => {detail = time.id}}>
                {t("state_"+time.state.name.toLowerCase())}
                {#if time.state.name.toLowerCase() == 'pending' && docLinks[time.id]}
                <ul>
                    {#each Object.entries(docLinks[time.id]) as [a,b]}
                    <li>
                        <a href="/document/{a}/view" {onclick}>{b}</a>
                    </li>
                    {/each}
                </ul>
                {/if}
            </td>
            {/if}
        </tr>
        {/each}
    </tbody>
</table>
{/if}
