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

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

    import LineEditor       from '../../Components/LineEditor.svelte';
    import MarkdownEditor   from '../../Components/MarkdownEditor.svelte';
    import ParentSelector   from './ParentSelector.svelte';
    import PermissionEditor from '../../Components/PermissionEditor.svelte';
    import Notes            from '../notes/RelatedNotes.svelte';
    import StateSelector    from '../../Components/StateSelector.svelte';
    import RequiredTasks    from './RequiredTasks.svelte';
    import TagList          from '../tags/TagList.svelte';
    import TaskList         from './TaskList.svelte';

	let eventSource    = $state(null);
    let { id }         = $props();
    let children       = $state(null);
    let dummy          = $derived(updateOn(id));
    let est_time = $state({sum:0});
    let select_parent  = $state(false);
    let project        = $state(null);
    const router       = useTinyRouter();
    let showSettings   = $state(router.fullPath.endsWith('/edit'));
    let show_closed    = $state(false);
    let task           = $state(null);

    $effect(() => {
        if (!eventSource) eventSource = eventStream(null,handleUpdateEvent,null);
        updateOn(id)
    });

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

    async function addMember(newMember){
        return await update({new_member:+newMember.id});
    }

    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;
            yikes();
        } else {
            error(resp);
        }
    }

    async function dropMember(member){
        update({drop_member:member.user.id});
    }

    async function getCandidates(text){
        const origin     = task.parent ? task.parent.members : project.members;
        return Object.values(origin)
            .filter(member => member.user.name.toLowerCase().includes(text.toLowerCase()))
            .map(member => { return {...member.user,display:member.user.name}});

    }

    function gotoKanban(){
        if (!project) return;
        router.navigate(`/project/${project.id}/kanban`)
    }

    function gotoProject(){
        if (!project) return;
        router.navigate(`/project/${project.id}/view`)
    }

	function handleUpdateEvent(evt){
		let json = JSON.parse(evt.data);
		if (json.task) {
			if (json.task.id == id) updateOn(id);
			if (json.task.parent_task_id == id) children[json.task.id] = json.task;
		}
	}

	async function loadChildren(){
        const url  = api('task/list');
        const data = {
            parent_task_id : +task.id,
            show_closed    : show_closed
        };
        const resp = await post(url,data);
        if (resp.ok){
            yikes();
            children = await resp.json();
        } else error(resp);
    }

    async function loadParent(){
        const url  = api(`task/${task.parent_task_id}`);
        const resp = await get(url);
        if (resp.ok){
            task.parent = await resp.json();
        } else error(resp);
    }

    async function loadTask(){
        const url  = api(`task/${id}`);
        const resp = await get(url);
        if (resp.ok){
            yikes();
            task     = await resp.json();
            if (task.show_closed) show_closed = true;
            loadChildren();
            if (task.project_id) loadProject();
            if (task.parent_task_id) loadParent();
        } else error(resp);
    }

    async function loadProject(){
        const url  = api(`project/${task.project_id}`);
        const resp = await get(url);
        if (resp.ok){
            project = await resp.json();
            yikes();
        } else error(await resp.text());
    }

    function parentClick(ev){
        ev.preventDefault();
        if (!task.parent_task_id) return;
        router.navigate(`/task/${task.parent_task_id}/view`);
        return false;
    }

    function parentRightClick(ev){
        ev.preventDefault();
        select_parent = true;
        return false;
    }

    function showClosed(){
        show_closed = !show_closed;
        children = null;
        loadChildren();
    }

    function showPrjFiles(){
        var url = `/files/project/${project.id}`;
        window.open(url, '_blank').focus();
    }

    function toggleSettings(){
        showSettings = !showSettings;
    }

    function unlink_parent(){
        update({parent_task_id:null});
    }

    async function update(data){
        const url  = api(`task/${id}`);
        const resp = await patch(url,data);
        if (resp.ok){
            yikes();
            let json = await resp.json();
            if (json.members) task.members = json.members;
            return true;
        } else {
            error(resp);
            return false;
        }
    }

    function updateClosed(){
        if (update({show_closed:task.show_closed})) setTimeout(loadTask,50);
    }

    function updateNoIndex(){
        if (update({no_index:task.no_index})) setTimeout(loadTask,50);
    }

    function updateOn(id){
        //task = null;
        loadTask();
    }

    function update_parent(newVal){
        select_parent = false;
        update({parent_task_id:newVal.id});
    }

    function updatePermission(user_id,permission){
        let members      = {};
        members[user_id] = permission.code;
        update({members:members});
    }

	onDestroy(() => {
		if (eventSource) eventSource.close();
	});
</script>

<svelte:head>
    <title>Umbrella – {t('task')}: {task?.name}</title>
</svelte:head>

{#if task}
<div class={`task grid2 prio_${task.total_prio} p${Math.floor(task.total_prio/10)*10} p${task.total_prio % 10}`} >
    {#if project}
    <div>{t('project')}</div>
    <div class="project">
        <a href="#" onclick={gotoProject}>{project.name}</a>
        <button class="symbol" title={t('kanban')} onclick={gotoKanban}></button>
        <button class="symbol" title={t('files')} onclick={showPrjFiles}></button>
    </div>
    {/if}
    <div>{t('parent_task')}</div>
    <div class="parent">
        {#if select_parent}
        <ParentSelector {task} {project} select={update_parent} />
        {:else}
        {#if task.parent}
        <a href="/task/{task.parent.id}/view" onclick={parentClick} oncontextmenu={parentRightClick}>{task.parent.name}</a>
        <button class="symbol" title={t('unlink')} onclick={unlink_parent}></button>
        {/if}
        <button class="symbol" title={t('edit')} onclick={parentRightClick}></button>
        {/if}
    </div>
    <div>{t('task')}</div>
    <div class="name">
        <LineEditor bind:value={task.name} editable={true} onSet={val => update({name:val})} />
        <button class="symbol" title={t('settings')} onclick={toggleSettings}></button>
        <button class="symbol" title={t('timetracking')} onclick={addTime}></button>
    </div>
    <div>{t('state')}</div>
    <div>
        <StateSelector selected={task.status} onchange={val => update({status:val})} {project} />
    </div>
    {#if task.description}
    <div>{t('description')}</div>
    <MarkdownEditor store_id="task/{task.id}/description" bind:value={task.description} editable={true} onSet={val => update({description:val})} />
    {/if}
    {#if !showSettings && task.start_date}
        <div>{t('start_date')}</div>
        <div class="start date">{task.start_date}</div>
    {/if}
    {#if !showSettings && task.due_date}
        <div>{t('due_date')}</div>
        <div class="due date">{task.due_date}</div>
    {/if}
    {#if task.est_time}
        <div>{t('estimated_time')}</div>
        <div class="estimated time">{task.est_time} h</div>
    {/if}
    {#if showSettings}
        <div>{t('extended_settings')}</div>
        <label>
            <input type="checkbox" bind:checked={task.show_closed} onchange={updateClosed} />
            {t('display_closed_tasks')}
        </label>

        <div></div>
        <label>
            <input type="checkbox" bind:checked={task.no_index} onchange={updateNoIndex} />
            {t('hide_on_index_page')}
        </label>

        <div>{t('members')}</div>
        <div>
            <PermissionEditor members={task.members} {addMember} {dropMember} {getCandidates} {updatePermission} />
        </div>
        <div>{t('start_date')}</div>
        <div>
            <input type="date" bind:value={task.start_date} onchange={() => update({start_date:task.start_date})} />
        </div>

        <div>{t('due_date')}</div>
        <div>
            <input type="date" bind:value={task.due_date} onchange={() => update({due_date:task.due_date})} />
        </div>

        <div>{t('estimated_time')}</div>
        <div>
            <input type="number" bind:value={task.est_time} onchange={() => update({est_time:task.est_time})} />&nbsp;h
        </div>

        <div>{t('priority')}</div>
        <div>
            <input type="number" bind:value={task.priority} onchange={() => update({priority:task.priority})} />
        </div>

        <div>{t('depends_on')}</div>
        <div>
            <RequiredTasks {task} />
        </div>
    {:else}
    <div>{t('members')}</div>
    <div class="members">
        <ul>
            {#each Object.values(task.members) as member}
            <li>{member.user.name} ({t('permission_'+member.permission.name.toLowerCase())})</li>
            {/each}
        </ul>
    </div>
    {/if}
    <div>{t('tags')}</div>
    <div class="tags">
        <TagList module="task" {id} user_list={Object.keys(task.members).map(id => +id)} />
    </div>

    <div>
        {t('subtasks')}
        <button onclick={addChild} >{t('add_object',{object:t('subtask')})}</button>
        {#if !show_closed}
        <button onclick={showClosed}>{t('display_closed')}</button>
        {/if}
    </div>
    <div class="children">
        {#if children}
        <TaskList {eventSource} states={project?.allowed_states} tasks={children} {est_time} show_closed={task.show_closed} />
        {/if}
    </div>

    <h3>{t('notes')}</h3>
    <div>
    <Notes module="task" entity_id={id} />
    </div>
</div>
{/if}

