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

    import { api, eventStream, get, patch }    from '../../urls.svelte.js';
    import { error, yikes }  from '../../warn.svelte';
    import { t }             from '../../translations.svelte.js';

    let filter = $state(null);
    let lower_filter = $derived(filter.toLowerCase());
    let inverted_filter = $state(false);
    let projects = $state({});
    let router = useTinyRouter();
    let tasks = $state(null);
    let bounds = $state({offset:0,limit:256});
    let loading = $state(true);
    let map = $state({});
    let hidden = $state({});

    async function changeState(idx,state){
        const task = tasks[idx];
        const tid = task.id;
        const prj  = projects[task.project_id];
        const stat = Object.keys(prj.allowed_states).find(k => prj.allowed_states[k] === state);
        const url  = api(`task/${tid}`);
        const resp = await patch(url,{status:stat});
        if (resp.ok){
            tasks[idx] = await resp.json();
        } else error(resp);
    }

    function abort(idx){
        changeState(idx,'CANCELLED');
    }

    function complete(idx){
        changeState(idx,'COMPLETE');
    }

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

    function filterApplies(task){
        if (!filter) return !inverted_filter;
        if (task.name.toLowerCase().includes(lower_filter)) return !inverted_filter;
        if (task.description.source.toLowerCase().includes(lower_filter)) return !inverted_filter;
        if (projects[task.project_id].name.toLowerCase().includes(lower_filter)) return !inverted_filter;
        if (task.parent_task_id){
            const parent = map[task.parent_task_id];
            if (parent && parent.name.toLowerCase().includes(lower_filter)) return !inverted_filter;
        }

        return inverted_filter;
    }

    function go(module, id){
        router.navigate(`/${module}/${id}/view`);
    }

    async function loadProject(pid){
        const url  = api(`project/${pid}`);
        const resp = await get(url);
        if (resp.ok){
            projects[pid] = await resp.json();
        } else error(resp);
    }

    async function load(){
        const url  = api(`task?offset=${bounds.offset}&limit=${bounds.limit}`);
        const resp = await get(url);
        if (resp.ok){
            let newTasks = await resp.json();
            if (bounds.offset == 0) {
                tasks = newTasks;
            } else tasks = tasks.concat(newTasks);
            loading = newTasks.length;
            if (loading){
                for (let task of newTasks) {
                    map[task.id] = task;
                    if (task.parent_task_id) hidden[task.parent_task_id] = true;
                    let pid = task.project_id;
                    if (pid && !projects[pid]) await loadProject(pid);
                }
                bounds.offset += bounds.limit;
                load();
            }
        } else error(resp);
    }

    function open(idx){
        changeState(idx,'OPEN');
    }

    function postpone(idx){
        changeState(idx,'PENDING');
    }

    function start(idx){
        changeState(idx,'STARTED');
    }

    onMount(load);
</script>

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

<fieldset>
    <legend>{loading ? t('loading_object',{object:t('task_list')}) : t('task_list')}</legend>
    <div class="filter">
        <label>
            {t('filter')}: <input type="text" bind:value={filter} >
        </label>
        {#if filter}
        <label>
            <input type="checkbox" bind:checked={inverted_filter} />
            {t('invert_filter')}
        </label>
        {/if}
    </div>
    {#if tasks}
    <table>
        <thead>
            <tr>
                <th>{t('name')}</th>
                <th>{t('project')} ({t('parent_task')})</th>
                <th>{t('state')}</th>
                <th>{t('start_date')}</th>
                <th>{t('due_date')}</th>
                <th>{t('users')}</th>
                <th>{t('actions')}</th>
            </tr>
        </thead>
        <tbody>
            {#each tasks as task,idx}
            {#if task.status > 10 && task.status < 60 && !task.no_index && projects[task.project_id]?.status < 60 && !hidden[task.id] && filterApplies(task)}
            <tr title={task.description.source}>
                <td onclick={() => go('task',task.id)}>{task.name}</td>
                <td>
                    <a href="#" onclick={() => go('project',task.project_id)}> {projects[task.project_id]?.name}</a>
                    {#if task.parent_task_id}
                    : <a href="#" onclick={() => go('task',task.parent_task_id)}>{map[task.parent_task_id]?.name}</a>
                    {/if}
                </td>
                <td>
                    {task.status % 10 ? projects[task.project_id]?.allowed_states[task.status] : t('state_'+projects[task.project_id]?.allowed_states[task.status]?.toLowerCase())}
                </td>
                <td>
                    {task.start_date}
                </td>
                <td>
                    {task.due_date}
                </td>
                <td>
                    <ul>
                    {#each Object.values(task.members) as member}
                        <li>
                            {member.user.name}:
                            {t('permission_'+member.permission.name.toLowerCase())}
                        </li>
                    {/each}
                    </ul>
                </td>
                <td>
                    <button class="symbol" onclick={() => edit(task.id)} title={t('edit')} ></button>
                    <button class="symbol" onclick={() => postpone(idx)} title={t('postpone')} ></button>
                    <button class="symbol" onclick={() => open(idx)} title={t('state_open')}></button>
                    <button class="symbol" onclick={() => start(idx)} title={t('start')} ></button>
                    <button class="symbol" onclick={() => complete(idx)} title={t('complete')} ></button>
                    <button class="symbol" onclick={() => abort(idx)} title={t('abort')} ></button>
                </td>
            </tr>
            {/if}
            {/each}
        </tbody>
    </table>
    {/if}
</fieldset>