<script>
    import { onMount }       from 'svelte';
    import { useTinyRouter } from 'svelte-tiny-router';

    import { dragged }       from './dragndrop.svelte';
    import { api }           from '../../urls.svelte';
    import { error, yikes }  from '../../warn.svelte';
    import { t }             from '../../translations.svelte';
    import { timetrack }     from '../../user.svelte';
    import { now }           from '../../time.svelte';

    import TaskList          from './TaskList.svelte';
    import LineEditor        from '../../Components/LineEditor.svelte';

    let {
        est_time,
        lastEvent,
        show_closed,
        siblings,
        states = {},
        task
    } = $props();
    let children = $state(null);
    let deleted  = $state(false);
    const router = useTinyRouter();
    let start    = 0;

    function addSubtask(){
        router.navigate(`/task/${task.id}/add_subtask`);
    }

    async function addTime(){
        const url  = api(`time/track_task/${task.id}`);
        const resp = await fetch(url,{
            credentials : 'include',
            method      : 'POST',
            body        : now()
        }); // create new time or return time with assigned tasks
        if (resp.ok) {
            const track = await resp.json();
            timetrack.running = track;
        } else {
            error(resp);
        }
    }

    async function deleteTask(){
        if (confirm(t('confirm_delete',{element:task.name}))){
            const url  = api(`task/${task.id}`);
            const resp = await fetch(url,{
                credentials : 'include',
                method      : 'DELETE'
            });
            if (resp.ok){
                deleted = true;
            } else {
	            error(resp);
            }
        }
    }

    function ondragstart(ev){
        ev.stopPropagation();
        dragged.element  = task;
        dragged.siblings = siblings;
    }


    async function ondrop(ev){
        ev.stopPropagation();
        if (dragged.element.id == task.id) return;
        const  url = api(`task/${dragged.element.id}`);
        const resp = await fetch(url,{
            credentials : 'include',
            method      : 'PATCH',
            body        : JSON.stringify({ parent_task_id : task.id})
        });
        if (resp.ok) {
            yikes();
        } else {
            error(resp);
        }
        return false;
    }

    async function loadChildren(){
        const url  = api('task/list');
        const data = {
            parent_task_id : +task.id,
            show_closed    : show_closed
        };
        if (task.show_closed) data.show_closed = true;
        const resp = await fetch(url,{
            credentials : 'include',
            method      : 'POST',
            body        : JSON.stringify(data)
        });
        if (resp.ok){
            children = await resp.json();
            yikes();
        } else {
            error(resp);
        }
    }

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

    async function patchTask(changeset){
        const url  = api(`task/${task.id}`);
        const resp = await fetch(url,{
            credentials : 'include',
            method      : 'PATCH',
            body        : JSON.stringify(changeset)
        });
        if (resp.ok){
            task = await resp.json();
            return true;
        } else {
            error(resp);
            return false;
        }
    }

    async function setName(newName){
        return await patchTask({name:newName});
    }

    function map_state(tx){
        for (let [code,name] of Object.entries(states)){
            if (tx == name) return {status:+code};
        }
        return {state:0};
    }

    if (task.est_time){
        est_time.sum += task.est_time;
    }

    $effect(() => {
		if (children && lastEvent && lastEvent.task) {
			if (lastEvent.event == 'delete' || lastEvent.task.parent_task_id != task.id){
				delete children[lastEvent.task.id];
			} else {
				children[lastEvent.task.id] = lastEvent.task;
			}
		}
	});

    onMount(loadChildren);
</script>

{#if !deleted}
<li draggable="true" {ondrop} ondragover={e => e.preventDefault()} {ondragstart} class="task {states[task.status]?.toLowerCase()}">
    <LineEditor bind:value={task.name} onclick={openTask} editable={true} onSet={setName} type="a" href={`/task/${task.id}/view`} />
    {#if task.est_time}
    <span class="estimated_time">({+task.est_time}&nbsp;h)</span>
    {/if}
    <button class="symbol" title={t('drag_n_drop')}></button>
    {#if states[task.status] != 'PENDING'}
    <button class="symbol" title={t('postpone')} onclick={() => patchTask(map_state('PENDING'))}></button>
    {/if}
    {#if states[task.status] != 'OPEN'}
    <button class="symbol" title={t('do_open')} onclick={() => patchTask(map_state('OPEN'))}></button>
    {/if}
    {#if states[task.status] != 'STARTED'}
    <button class="symbol" title={t('started')} onclick={() => patchTask(map_state('STARTED'))}></button>
    {/if}
    {#if states[task.status] != 'COMPLETE'}
    <button class="symbol" title={t('complete')} onclick={() => patchTask(map_state('COMPLETE'))}></button>
    {/if}
    {#if states[task.status] != 'CANCELLED'}
    <button class="symbol" title={t('abort')} onclick={() => patchTask(map_state('CANCELLED'))} ></button>
    {/if}
    <button class="symbol" title={t('delete_object',{object:t('subtask')})} onclick={deleteTask} ></button>
    <button class="symbol" title={t('add_object',{object:t('subtask')})} onclick={addSubtask}></button>
    <button class="symbol" title={t('timetracking')} onclick={addTime}></button>
    {#if children}
    <TaskList {states} {lastEvent} tasks={children} {est_time} {show_closed} />
    {/if}
</li>
{/if}
