<script setup lang="ts">
import { Ref, computed, ref } from 'vue';
import Button from 'primevue/button';
import ContextMenu from 'primevue/contextmenu';
import { useConfirm } from 'primevue/useconfirm';
import { listen } from '@tauri-apps/api/event';
import { getCurrentWindow } from '@tauri-apps/api/window';
import Onboarding from './Onboarding.vue';
import { invoke } from '../invoke';
import { useClientStore, usePrfStore } from '../stores';
import { useI18n } from 'vue-i18n';

const { t } = useI18n();

const prf = usePrfStore();
const client = useClientStore();
const confirmDialog = useConfirm();

type StartStatus = 'ready' | 'preparing' | 'running';
const startStatus: Ref<StartStatus> = ref('ready');

const startline = async (force: boolean, refresh: boolean) => {
    startStatus.value = 'preparing';

    if (!force) {
        const start_check: object[] = await invoke('start_check');
        if (start_check.length > 0) {
            const message = start_check.map((o) => {
                if ('MissingRemotePackage' in o) {
                    return `${t('start.error.package')}: ${o.MissingRemotePackage}`;
                } else if ('MissingLocalPackage' in o) {
                    return `${t('start.error.package')}: ${o.MissingLocalPackage}`;
                } else if ('MissingDependency' in o) {
                    return `${t('start.error.dependency')}: ${(o.MissingDependency as string[]).join(' ')}`;
                } else if ('MissingTool' in o) {
                    return `${t('start.error.tool')}: ${o.MissingTool}`;
                } else {
                    return t('start.error.unknown');
                }
            });
            confirmDialog.require({
                message: message.join('\n'),
                header: t('start.failed'),
                acceptLabel: t('start.accept'),
                rejectLabel: t('cancel'),
                accept: () => {
                    startline(true, refresh);
                },
            });
            startStatus.value = 'ready';
            return;
        }
    }
    try {
        await invoke('save_current_profile');
        await invoke('startline', { refresh });
    } catch (_) {
        startStatus.value = 'ready';
    }
};

const kill = async () => {
    await invoke('kill');
};

const disabledTooltip = computed(() => {
    if (prf.current?.data.sgt.target.length === 0) {
        return t('start.tooltip.game');
    }
    if (prf.current?.data.sgt.amfs.length === 0) {
        return t('start.tooltip.amfs');
    }
    if (
        prf.current?.data.sgt.hook === null ||
        prf.current?.data.sgt.hook === undefined
    ) {
        return t('start.tooltip.segatools');
    }
    return null;
});

listen('launch-start', () => {
    startStatus.value = 'running';
    getCurrentWindow().minimize();
});

listen('launch-end', () => {
    startStatus.value = 'ready';
    getCurrentWindow().unminimize();
    getCurrentWindow().setFocus();
});

const createShortcut = async () => {
    const current = prf.current;
    if (current !== null) {
        await invoke('create_shortcut', {
            profileMeta: current.meta,
        });
    }
};

const hasShortcut = ref(false);

(async () => {
    hasShortcut.value = (
        (await invoke('list_platform_capabilities')) as string[]
    ).includes('shortcut');
})();

const menuItems = computed(() => {
    let base = [
        {
            label: t('start.button.unchecked'),
            icon: 'pi pi-exclamation-circle',
            command: async () => await startline(true, false),
        },
    ];
    let baseTail = [
        {
            label: t('start.button.help'),
            icon: 'pi pi-question-circle',
            command: () => {
                onboardingFirstTime.value = false;
                onboardingVisible.value = true;
            },
        },
    ];
    if (prf.current === null) {
        return [];
    }
    if (hasShortcut.value === true) {
        base = [
            ...base,
            {
                label: t('start.button.shortcut'),
                icon: 'pi pi-link',
                command: createShortcut,
            },
        ];
    }
    if (prf.current.meta.game === 'chunithm') {
        return [...base, ...baseTail];
    }
    if (prf.current.meta.game === 'ongeki') {
        return [
            {
                label: t('start.button.refresh'),
                icon: 'pi pi-sync',
                command: async () => await startline(false, true),
            },
            ...base,
            {
                label: t('start.button.cache'),
                icon: 'pi pi-trash',
                command: async () => await invoke('clear_cache'),
            },
            ...baseTail,
        ];
    }
});

const menu = ref();

const showContextMenu = (event: Event) => {
    event.preventDefault();
    menu.value.show(event);
};

const onboardingVisible = ref(false);
const onboardingFirstTime = ref(false);

const tryStart = () => {
    const game = prf.current?.meta.game;

    if (game !== undefined) {
        if (client.onboarded.includes(game)) {
            startline(false, false);
        } else {
            onboardingVisible.value = true;
            onboardingFirstTime.value = true;
            client.setOnboarded(game);
        }
    }
};
</script>

<template>
    <Onboarding
        :visible="onboardingVisible"
        :first-time="onboardingFirstTime"
        :on-finish="
            () => {
                onboardingVisible = false;
                if (onboardingFirstTime === true) {
                    startline(false, false);
                }
            }
        "
    />
    <ContextMenu ref="menu" :model="menuItems" />
    <Button
        v-if="startStatus === 'ready'"
        v-tooltip="disabledTooltip"
        :disabled="disabledTooltip !== null"
        icon="pi pi-play"
        label="START"
        aria-label="start"
        size="small"
        class="m-2.5"
        @click="tryStart"
        @contextmenu="showContextMenu"
    />
    <Button
        v-else-if="startStatus === 'preparing'"
        disabled
        icon="pi pi-spin pi-spinner"
        :label="t('start.button.start')"
        aria-label="start"
        size="small"
        class="m-2.5"
    />
    <Button
        v-else
        :disabled="false"
        icon="pi pi-ban"
        :label="t('start.button.stop')"
        aria-label="stop"
        size="small"
        class="m-2.5"
        @click="kill()"
    />
</template>
