<!--
  -   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 { preventDefault } from 'svelte/legacy';

    import {ArrowLeftOutline} 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";


    let selected: number | null = $state(null);

    let selectedBranch: string = $state("master");
    let searchValue: string = $state("");
    let dirty = $state(false);

    let selectedPath: string | null = $state(null);
    let pathSearchValue: string = $state("");


    async function createBranch(name: string | null = null): Promise<string> {
        return new Promise(async (resolve) => {
            if (!name) {
                name = prompt("Branch name:");

                if (!name) {
                    resolve("");
                    return;
                }
            }
            if (name) {
                selected = null;
                await $pageRepo.createBranch(name);
                let inter = setInterval(() => {
                    branches.reload();
                    if ($branches.includes(name!)) {
                        selectedBranch = name!;
                        searchValue = "";
                        clearInterval(inter);

                        resolve(name!);
                    }
                }, 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;
    }

    async function newAnnouncement() {
        const title = prompt("Title: ");

        if (!title) {
            return;
        }

        const slug = title.toLowerCase().replace(/ /g, "-");

        const branch = await createBranch(slug)

        selectedPath = "announcements/de/"

        await $pageRepo.createFile(`${selectedPath}${slug}.md`, branch, slug, title);
        reload();

        const pages = await $pageRepo.listPages(branch);

        const page = pages.find(page => page.path === `${selectedPath}${slug}.md`);
        
        if (page) {
            changePage(page.id);
        } else {
            alert("Error creating page");
        }
    }
    let pagesFuture = $derived($pageRepo.listPages(selectedBranch));
    let availableBranches = $derived($branches.map((branch) => ({
        name: branch,
        value: branch
    })));
</script>

<div class="flex flex-col h-screen overflow-scroll">
    <Navbar>
        <NavBrand href="#">
            <ArrowLeftOutline></ArrowLeftOutline>
            <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 onclick={() => createFile()} color="alternative" disabled={!selectedPath}>Create File
                                </Button>
                                <Button onclick={() => deleteBranch(false)} color="none">Delete Branch</Button>
                            {:else}
                                <Button onclick={() => createBranch()}>Create Branch</Button>
                            {/if}
                        </div>
                    </div>
                    <ul>
                        {#if (selectedPath)}
                            {@const value = pagesMap.get(selectedPath) || []}
                            {#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"
                                    onclick={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}
                        {:else}
                            <Button onclick={newAnnouncement}>Neue Ankündigung</Button>
                        {/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>