<script setup lang="ts">
import { Ref, computed, onMounted, ref } from 'vue';
import Button from 'primevue/button';
import ConfirmDialog from 'primevue/confirmdialog';
import Dialog from 'primevue/dialog';
import InputIcon from 'primevue/inputicon';
import InputText from 'primevue/inputtext';
import ProgressBar from 'primevue/progressbar';
import ScrollPanel from 'primevue/scrollpanel';
import Tab from 'primevue/tab';
import TabList from 'primevue/tablist';
import TabPanel from 'primevue/tabpanel';
import TabPanels from 'primevue/tabpanels';
import Tabs from 'primevue/tabs';
import { listen } from '@tauri-apps/api/event';
import InfoPage from './InfoPage.vue';
import ModList from './ModList.vue';
import ModStore from './ModStore.vue';
import OptionList from './OptionList.vue';
import PatchList from './PatchList.vue';
import ProfileList from './ProfileList.vue';
import StartButton from './StartButton.vue';
import {
    useClientStore,
    useGeneralStore,
    usePkgStore,
    usePrfStore,
} from '../stores';
import { messageSplit, shouldPreferDark } from '../util';

document.documentElement.classList.toggle('use-dark-mode', shouldPreferDark());

const pkg = usePkgStore();
const prf = usePrfStore();
const general = useGeneralStore();
const client = useClientStore();

client.load();

pkg.setupListeners();

const pkgSearchTerm = ref('');

const isProfileDisabled = computed(() => prf.current === null);

const updateProgress: Ref<number | null> = ref(null);

listen<number>('update-progress', (ev) => {
    updateProgress.value = Math.floor(ev.payload * 100);
});

listen<undefined>('update-end', (_) => {
    updateProgress.value = null;
});

onMounted(async () => {
    const fetch_promise = pkg.fetch(true);

    await Promise.all([prf.reloadList(), prf.reload()]);

    if (prf.current !== null) {
        await pkg.reloadAll();
    }

    await fetch_promise;
});

const errorVisible = ref(false);
const errorMessage = ref('No error');
const errorHeader = ref('No header');

listen<{ message: string; header: string }>('invoke-error', (event) => {
    errorVisible.value = true;
    errorMessage.value = event.payload.message;
    errorHeader.value = event.payload.header;
});

listen<string>('launch-error', (event) => {
    errorVisible.value = true;
    errorMessage.value = event.payload;
    errorHeader.value = 'Launch error';
});

interface DownloadingStatus {
    ratio: number;
    pkg_key: string;
}
const downloading_status: Ref<DownloadingStatus[]> = ref([]);

const download_value = computed(() => {
    return (
        downloading_status.value.map((v) => v.ratio).reduce((a, v) => a * v) *
        100
    );
});

const downloadProgressText = computed(() => {
    if (download_value.value < 7) {
        return '';
    }
    let pkgs = `${downloading_status.value.length} package${downloading_status.value.length === 1 ? '' : 's'}`;
    if (download_value.value < 14) {
        return pkgs;
    } else {
        return `${pkgs} (${Math.floor(download_value.value)}%)`;
    }
});

listen<DownloadingStatus>('download-progress', (event) => {
    let status = downloading_status.value.find(
        (v) => v.pkg_key === event.payload.pkg_key
    );

    if (status === undefined) {
        status = {
            ratio: 0,
            pkg_key: event.payload.pkg_key,
        };
        downloading_status.value.push(status);
    }
    status.ratio = event.payload.ratio;

    const remove = () => {
        if (status !== undefined) {
            downloading_status.value = downloading_status.value.filter(
                (v) => v.pkg_key !== event.payload.pkg_key
            );
        }
    };

    if (status.ratio === 1.0) {
        remove();
    }

    setTimeout(() => remove, 10_000);
});
</script>

<template>
    <main
        :class="
            client.scaleFactor === 's'
                ? 'main-scale-s'
                : client.scaleFactor === 'm'
                  ? 'main-scale-m'
                  : client.scaleFactor === 'l'
                    ? 'main-scale-l'
                    : 'main-scale-xl'
        "
    >
        <div
            v-if="downloading_status.length > 0"
            class="download-progress-bg"
        ></div>
        <ProgressBar
            v-if="downloading_status.length > 0"
            :value="download_value"
            class="download-progress"
            >{{ downloadProgressText }}</ProgressBar
        >
        <ConfirmDialog>
            <template #message="{ message }">
                <ScrollPanel
                    v-if="messageSplit(message).length > 5"
                    style="width: 100%; height: 40vh"
                >
                    <p v-for="m in messageSplit(message)">
                        {{ m }}
                    </p></ScrollPanel
                >
                <div v-else>
                    <p v-for="m in messageSplit(message)">
                        {{ m }}
                    </p>
                </div>
            </template>
        </ConfirmDialog>
        <Dialog
            modal
            :visible="errorVisible"
            :closable="false /*this shit doesn't work */"
            :header="errorHeader"
            :style="{ width: '50vw' }"
        >
            <div class="flex flex-col gap-4">
                {{ errorMessage }}
                <Button
                    class="m-auto"
                    label="OK"
                    @click="errorVisible = false"
                />
            </div>
        </Dialog>
        <Dialog
            modal
            :visible="updateProgress !== null"
            :closable="false"
            header="Updating"
            :style="{ width: '200px' }"
        >
            <ProgressBar :value="updateProgress ?? undefined" />
        </Dialog>

        <Tabs
            lazy
            :value="client.currentTab"
            v-on:update:value="
                (value) => {
                    client.currentTab = value as string;
                    client.save();
                }
            "
            class="h-screen"
        >
            <div class="fixed w-full flex z-100">
                <TabList class="grow" :show-navigators="false">
                    <Tab value="users"><div class="pi pi-home"></div></Tab>
                    <Tab
                        :disabled="
                            isProfileDisabled || pkg.networkStatus !== 'online'
                        "
                        value="rmt"
                        ><div class="pi pi-download"></div
                    ></Tab>
                    <Tab :disabled="isProfileDisabled" value="loc"
                        ><div class="pi pi-box"></div
                    ></Tab>
                    <Tab
                        v-if="(prf.current?.data.sgt.target.length ?? 0) > 0"
                        value="patches"
                        ><div class="pi pi-ticket"></div
                    ></Tab>

                    <Tab :disabled="isProfileDisabled" value="cfg"
                        ><div class="pi pi-cog"></div
                    ></Tab>
                    <Tab value="info"
                        ><div class="pi pi-info-circle"></div
                    ></Tab>

                    <div class="grow"></div>

                    <div class="flex gap-4">
                        <div
                            class="flex"
                            v-if="
                                ['loc', 'rmt', 'cfg'].includes(
                                    client.currentTab
                                )
                            "
                        >
                            <InputIcon class="self-center mr-2">
                                <i class="pi pi-search" />
                            </InputIcon>
                            <InputText
                                v-if="client.currentTab === 'cfg'"
                                style="min-width: 0; width: 25dvw"
                                class="self-center"
                                size="small"
                                placeholder="Search"
                                v-model="general.cfgSearchTerm"
                            />
                            <InputText
                                v-else
                                style="min-width: 0; width: 25dvw"
                                class="self-center"
                                size="small"
                                placeholder="Search"
                                v-model="pkgSearchTerm"
                            />
                        </div>
                        <Button
                            v-if="pkg.networkStatus === 'connecting'"
                            class="shrink self-center"
                            icon="pi pi-sync pi-spin"
                            size="small"
                            :disabled="true"
                        />
                        <Button
                            v-if="
                                pkg.networkStatus === 'offline' &&
                                !client.offlineMode
                            "
                            class="shrink self-center"
                            icon="pi pi-sync"
                            size="small"
                            @click="pkg.fetch(false)"
                        />
                        <Button
                            v-if="
                                pkg.networkStatus === 'online' &&
                                pkg.hasAvailableUpdates
                            "
                            icon="pi pi-download"
                            label="UPDATE ALL"
                            size="small"
                            class="mr-4 m-2.5"
                            @click="pkg.updateAll()"
                        ></Button>
                    </div>
                    <div class="grow"></div>
                    <StartButton />
                </TabList>
            </div>
            <TabPanels class="w-full grow mt-[3rem]">
                <TabPanel value="loc" v-if="!isProfileDisabled">
                    <ModList :search="pkgSearchTerm" />
                </TabPanel>
                <TabPanel value="rmt" v-if="!isProfileDisabled">
                    <ModStore :search="pkgSearchTerm" />
                </TabPanel>
                <TabPanel value="cfg" v-if="!isProfileDisabled">
                    <OptionList />
                </TabPanel>
                <TabPanel value="users">
                    <ProfileList />
                </TabPanel>
                <TabPanel value="patches" v-if="!isProfileDisabled">
                    <PatchList
                        v-if="
                            pkg.hasLocal('mempatcher-mempatcher') &&
                            prf.isPkgKeyEnabled('mempatcher-mempatcher')
                                .value === true
                        "
                    />
                    <div v-else>
                        Patches require <code>mempatcher</code> to be installed
                        and enabled.

                        <div>
                            <Button
                                label="Add mempatcher"
                                icon="pi pi-plus"
                                class="mt-3"
                                @click="
                                    () =>
                                        pkg.installFromKey(
                                            'mempatcher-mempatcher'
                                        )
                                "
                            />
                        </div>
                    </div>
                </TabPanel>
                <TabPanel value="info">
                    <InfoPage />
                </TabPanel>
            </TabPanels>
            <div
                v-if="
                    client.currentTab === 'users' ||
                    client.currentTab === 'info'
                "
            >
                <img
                    v-if="prf.current?.meta.game === 'ongeki'"
                    src="/sticker-ongeki.svg"
                    class="fixed bottom-0 right-0 z-999"
                />
                <img
                    v-else-if="prf.current?.meta.game === 'chunithm'"
                    src="/sticker-chunithm.svg"
                    class="fixed bottom-0 right-0 z-999"
                />
            </div>
        </Tabs>
    </main>
</template>

<style lang="css">
@import 'tailwindcss';
@import 'primeicons/primeicons.css';

.p-tablist-tab-list {
    height: 3rem;
}

html,
body {
    margin: 0;
    padding: 0;
}

.main-scale-s {
    zoom: 1;
}

.main-scale-m {
    zoom: 1.25;
}

.main-scale-l {
    zoom: 1.4;
}

.main-scale-xl {
    zoom: 1.7;
}

.p-tablist {
    background-color: #ffffff !important;
    border-bottom: white 10px !important;
}

.p-tab {
    border-bottom: none !important;
}
.p-tablist-active-bar {
    display: none !important;
}

.p-tooltip {
    min-width: 300px;
}

.p-progressbar,
.p-progressbar-value,
.p-progressbar-label {
    transition-duration: 0s !important;
}

.download-progress {
    position: fixed !important;
    bottom: 0;
    left: 5vw;
    width: 90vw;
    z-index: 10000 !important;
    margin: 20px auto;
}
.download-progress-bg {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100vw;
    height: 60px;
    background-color: var(--p-surface-900);
    border-top: 1px solid var(--p-surface-600);
    z-index: 998;
}
</style>
