<!--
  -   This file is a part of the SteamWar software.
  -
  -   Copyright (C) 2023 SteamWar.de-Serverteam
  -
  -   This program is free software: you can redistribute it and/or modify
  -   it under the terms of the GNU Affero General Public License as published by
  -   the Free Software Foundation, either version 3 of the License, or
  -   (at your option) any later version.
  -
  -   This program is distributed in the hope that it will be useful,
  -   but WITHOUT ANY WARRANTY; without even the implied warranty of
  -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  -   GNU Affero General Public License for more details.
  -
  -   You should have received a copy of the GNU Affero General Public License
  -   along with this program.  If not, see <https://www.gnu.org/licenses/>.
  -->

<script lang="ts">
    import {ArrowLeftSolid} from "flowbite-svelte-icons";
    import {Button, Card, Navbar, NavBrand, Spinner} from "flowbite-svelte";
    import {mapToMap, nameRegex} from "../util.ts";
    import TypeAheadSearch from "../components/TypeAheadSearch.svelte";
    import {branches} from "@stores/stores.ts";
    import Editor from "./edit/Editor.svelte";
    import {pageRepo} from "@repo/page.ts";

    $: pagesFuture = $pageRepo.listPages(selectedBranch);

    let selected: number | null = null;

    let selectedBranch: string = "master";
    let searchValue: string = "";
    let dirty = false;

    let selectedPath: string | null = null;
    let pathSearchValue: string = "";

    $: availableBranches = $branches.map((branch) => ({
        name: branch,
        value: branch
    }));

    async function createBranch() {
        const name = prompt("Branch name:");
        if (name) {
            selected = null;
            await $pageRepo.createBranch(name);
            let inter = setInterval(() => {
                branches.reload();
                if ($branches.includes(name)) {
                    selectedBranch = name;
                    searchValue = "";
                    clearInterval(inter);
                }
            }, 1000);
        }
    }

    function changePage(id: number) {
        if (dirty) {
            if (confirm("You have unsaved changes. Are you sure you want to change the page?")) {
                selected = id;
                dirty = false;
            }
        } else {
            selected = id;
        }
    }

    async function deleteBranch(con: boolean) {
        if (selectedBranch !== "master") {
            let conf = con || confirm("Are you sure you want to delete this branch?");
            if (conf) {
                await $pageRepo.deleteBranch(selectedBranch);
                let inter = setInterval(() => {
                    branches.reload();
                    if (!$branches.includes(selectedBranch)) {
                        selectedBranch = "master";
                        searchValue = "";
                        clearInterval(inter);
                    }
                }, 1000);
            }
        } else {
            alert("You can't delete the master branch");
        }
    }

    async function createFile() {
        let name = prompt("File name:", "[Name].md");
        if (name) {
            await $pageRepo.createFile(`${selectedPath}${name}`, selectedBranch);
            reload();
        }
    }

    function reload() {
        const w = selectedBranch;
        selectedBranch = "###!";
        selectedBranch = w;
    }
</script>

<div class="flex flex-col h-screen overflow-scroll">
    <Navbar>
        <NavBrand href="#">
            <ArrowLeftSolid></ArrowLeftSolid>
            <span class="ml-4 self-center whitespace-nowrap text-xl font-semibold dark:text-white">
                Edit Pages
            </span>
        </NavBrand>
    </Navbar>
    <div class="p-4 flex-1">
        <div class="grid md:grid-cols-3 grid-cols-1 h-full gap-8">
            <Card class="h-full flex flex-col !max-w-full">
                {#await pagesFuture}
                    <Spinner/>
                {:then pages}
                    {@const pagesMap = mapToMap(pages)}
                    <div class="border-b border-b-gray-600 pb-2 flex justify-between">
                        <div>
                            <TypeAheadSearch items={availableBranches} bind:selected={selectedBranch} bind:searchValue/>
                            <TypeAheadSearch items={Array.from(pagesMap.keys()).map(value => ({value, name: value}))}
                                             bind:selected={selectedPath} bind:searchValue={pathSearchValue}
                                             maxItems={Number.MAX_VALUE} leftText={true}/>
                        </div>
                        <div>
                            {#if selectedBranch !== "master"}
                                <Button on:click={createFile} color="alternative" disabled={!selectedPath}>Create File
                                </Button>
                                <Button on:click={() => deleteBranch(false)} color="none">Delete Branch</Button>
                            {:else}
                                <Button on:click={createBranch}>Create Branch</Button>
                            {/if}
                        </div>
                    </div>
                    <ul>
                        {#if (selectedPath)}
                            {@const value = pagesMap.get(selectedPath) || []}
                            {#if value.length === 0}
                                <li class="p-4">No pages found</li>
                                <li class="p-4">Select a path on the top</li>
                            {/if}
                            {#each value as page}
                                {@const nameRegexExec = nameRegex.exec(page.path)}
                                {@const match = nameRegexExec ? nameRegexExec[0] : ""}
                                {@const startIndex = page.path.indexOf(match)}
                                {@const endIndex = startIndex + match.length}
                                <li class="p-4 transition-colors hover:bg-gray-700 cursor-pointer"
                                    on:click|preventDefault={() => changePage(page.id)}>
                                    <span class:text-orange-600={selected === page.id}>{page.path.substring(0, startIndex)}</span><span
                                        class="text-white"
                                        class:!text-orange-500={selected === page.id}>{match}</span><span
                                        class:text-orange-600={selected === page.id}>{page.path.substring(endIndex, page.path.length)}</span>
                                </li>
                            {/each}
                        {/if}
                    </ul>
                {:catch error}
                    <p>{error.message}</p>
                {/await}
            </Card>
            <Card class="!max-w-full" style="grid-column: 2/4">
                {#if selected}
                    <Editor pageId={selected} bind:branch={selectedBranch} on:reload={reload} bind:dirty/>
                {/if}
            </Card>
        </div>
    </div>
</div>