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

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

    import CompanySelector   from '../../Components/CompanySelector.svelte';
    import LineEditor        from '../../Components/LineEditor.svelte';
    import MarkdownEditor    from '../../Components/MarkdownEditor.svelte';
    import PermissionEditor  from '../../Components/PermissionEditor.svelte';
    import Notes             from '../notes/RelatedNotes.svelte';
    import StateSelector     from '../../Components/StateSelector.svelte';
    import Tags              from '../tags/TagList.svelte';
    import TaskList          from '../task/TaskList.svelte';

	let eventSource    = $state(null);
    let { id }         = $props();
    let lastEvent      = $state(null);
    let est_time       = $state({sum:0});
    let project        = $state(null);
    let router         = useTinyRouter();
    let showSettings   = $state(false);
    let tasks          = $state(null);
    let show_closed    = $state(false);
    let new_color      = $state({tag:null,color:'#00aa00'})

    let new_state = $state({code:null,name:null})
    let state_available=$derived(new_state.name && new_state.code && !project.allowed_states[new_state.code]);

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

    async function addState(){
        const url  = api(`project/${id}/state`);
        const resp = await post(url,new_state);
        if (resp.ok){
            const json = await resp.json();
            project.allowed_states[json.code] = json.name;
            yikes();
        } else {
            error(resp);
        }
    }

    function addTask(){
        router.navigate(`/project/${id}/add_task`);
    }

    function changeClosed(){
        update({show_closed:project.show_closed});
        loadTasks();
    }

    async function dropColor(tag){
        delete project.tag_colors[tag];
        update({tag_colors:project.tag_colors});
    }

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

    function handleCreate(evt){
        let json = JSON.parse(evt.data);
        json.event = 'create';
        lastEvent = json;
    }

    function handleDelete(evt){
        let json = JSON.parse(evt.data);
        json.event = 'delete';
        lastEvent = json;
    }

    function handleUpdate(evt){
        let json = JSON.parse(evt.data);
        json.event = 'update';
        lastEvent = json;
        if (json.project && json.project.id == project.id) project = json.project;
    }

    function kanban(){
        router.navigate(`/project/${id}/kanban`);
    }

    function load(){
		eventSource = eventStream(handleCreate,handleUpdate,handleDelete);
        loadProject();
    }

    async function loadProject(){
        const url  = api(`project/${id}`);
        const resp = await fetch(url,{credentials:'include'});
        if (resp.ok){
            project = await resp.json();
            yikes();
            loadTasks();
        } else {
            error(resp);
        }
    }

    async function loadTasks(){
        const url  = api('task/list');
        const data = {
            project_id:+id,
            show_closed:project.show_closed
        }
        const resp = await fetch(url,{
            credentials : 'include',
            method      : 'POST',
            body        : JSON.stringify(data)
        });
        if (resp.ok){
            tasks              = {};
            est_time.sum = 0;
            tasks              = await resp.json();
            yikes();
        } else {
            error(resp);
        }
    }

    function saveTagColor(){
        project.tag_colors[new_color.tag] = new_color.color;
        update({tag_colors:project.tag_colors});
    }

    function toggleSettings(){
        showSettings = !showSettings;
    }

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

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

    async function updateStateName(state_id,name){
        const url  = api(`project/${id}/state`);
        const resp = await patch(url,{id:state_id,name});
        if (resp.ok){
            const json = await resp.json();
            project.allowed_states[json.code]=json.name;
            yikes();
            return true;
        } else {
            error(resp);
            return false;
        }
    }

    function showClosed(){
        show_closed = !show_closed;
        loadTasks();
    }

    function showFiles(e){
        window.open(`/files/project/${id}`, '_blank').focus();
    }

    function showTimes(e){
        window.open(`/time?project=${id}`, '_blank').focus();
    }

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

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

<svelte:head>
    <title>Umbrella – {project?.name}</title>
</svelte:head>

{#if project}
<div class="project grid2">
    <div>{t('project')}</div>
    <div class="name">
        <LineEditor bind:value={project.name} editable={true} onSet={val => update({name:val})} />
    </div>
    <div>
        {t('options')}
    </div>
    <div>
        <button onclick={kanban}><span class="symbol"></span> {t('show_kanban')}</button>
        <button onclick={toggleSettings}><span class="symbol"></span> {t('settings')}</button>
    </div>
    <div>{t('state')}</div>
    <div>
        <StateSelector selected={project.status} onchange={val => update({status:+val})} {project} />
    </div>
    {#if project.company}
        <div>{t('company')}</div>
        <div class="company">{project.company.name}</div>
    {:else}
    {#if showSettings}
        <div>{t('company')}</div>
        <span><CompanySelector caption={t('select_company')} onselect={c => update({company_id:c.id})} /></span>
    {/if}
    {/if}
    <div>{t('context')}</div>
    <div>
        <button onclick={showFiles}>{t('files')}</button>
        <button>{t('models')}</button>
        <button onclick={showTimes}>{t('times')}</button>
    </div>
    {#if showSettings}
    <div>{t('extended_settings')}</div>
    <label>
        <input type="checkbox" bind:checked={project.show_closed} onchange={changeClosed} />
        {t('display_closed_tasks')}
    </label>
    <div class="em">{t('members')}</div>
    <div class="em">
        <PermissionEditor members={project.members} {updatePermission} {addMember} {dropMember} />
    </div>
    {#if project.allowed_states}
    {#each Object.keys(project.allowed_states) as key,idx}
    <div>
        {#if !idx}
        {t('allowed_states')}:
        {/if}
        {key}
    </div>
    <div>
        <LineEditor value={project.allowed_states[key]} editable={true} onSet={newName => updateStateName(+key,newName)} />
    </div>
    {/each}
    <div>
        <input type="number" bind:value={new_state.code} />
    </div>
    <div>
        <input type="text" bind:value={new_state.name} />
        {#if state_available}
        <button onclick={addState} >{t('add_state')}</button>
        {/if}
    </div>
    {/if}
    <div class="em">
        {t('custom_tag_colors')}
        <input type="color" bind:value={new_color.color} >
    </div>
    <div class="em">
        <label>
            {t('tag_name')}:
            <input type="text" bind:value={new_color.tag} />
        </label>
        <button onclick={saveTagColor}>{t('add_object',{object:t('color')})}</button>
    </div>
    {#each Object.entries(project.tag_colors) as [k,v]}
    <div style="background: {v}">{k}</div>
    <div class="em">
        <button onclick={e => dropColor(k)}>{t('delete')}</button>
    </div>
    {/each}
    {/if} <!-- settings -->

    {#if est_time.sum}
    <div>{t('estimated_time')}</div>
    <div class="estimated_time">{est_time.sum} h</div>
    {/if}

    <div>{t('description')}</div>
    <div class="description">
        <MarkdownEditor bind:value={project.description} editable={true} onSet={val => update({description:val})} />
    </div>

    <div>{t('tags')}</div>
    <div>
        <Tags module="project" {id} user_list={null} />
    </div>
    <div>
        {t('tasks')}
        <button onclick={addTask}>{t('add_object',{object:t('task')})}</button>
        <button onclick={showClosed}>{t('display_closed')}</button>
    </div>
    <div class="tasks">
        {#if tasks}
        <TaskList {tasks} {est_time} {lastEvent} {eventSource} states={project?.allowed_states} show_closed={show_closed || project.show_closed} />
        {/if}
    </div>
</div>
{/if}
<div class="notes">
    <h3>{t('notes')}</h3>
    <Notes module="project" entity_id={id} />
</div>
