<template>
    <div 
        class="root"
        :class="{ 'sidebar-visible': sidebarActive, 'vertical-mode': currentOrientation === 'vertical' }">
        <div class="sidebar">
            <div class="sidebar-left-strip">
                <draggable animation="150" 
                           @start="onStartDragBeatTab"
                           @end="onEndDragBeatTab"
                           v-model="beats" 
                           ghost-class="ghost" 
                           itemKey="name.value">
                    <template #item="{ element, index }">
                        <div 
                            :key="element.name.value"
                            class="sidebar-left-tab"
                            :class="{ 'active': index === activeBeatIndex }"
                            @click="activeBeatIndex = index">
                            <span v-if="element.saveDirty.value" class="unsaved">•</span>
                            <span class="name">{{ element.name.value }}</span>
                            <div
                                class="delete" 
                                @click="onDeleteBeat(index)" 
                                title="delete">
                                <div class="x">×</div>
                            </div>
                        </div>
                    </template>
                </draggable>
                <div 
                    class="tab-add"
                    @click="onAddNewBeat">
                    +
                </div>
            </div> 
            <div class="settings">
                <h1 class="title">{{ title }}</h1>
                <beat-settings :beat-index="activeBeatIndex" />
            </div>
            <div class="sidebar-toggle">
                <div class="buttons">
                    <div
                        class="quick-access-button"
                        :title="`${ sidebarActive ? 'Hide' : 'Show' } sidebar`"
                        @click="sidebarActive = !sidebarActive">
                        <icon icon-name="list" color="var(--color-ui-neutral-dark)" />
                    </div>
                    <div
                        class="quick-access-button"
                        title="Change orientation"
                        @click="toggleOrientation">
                        <icon icon-name="arrowClockwise" color="var(--color-ui-neutral-dark)" />
                    </div>
                    <div
                        class="quick-access-button"
                        title="Bake all tracks"
                        @click="bakeAll">
                        <icon icon-name="snowflake" color="var(--color-ui-neutral-dark)" />
                    </div>
                    <div
                        class="quick-access-button"
                        title="Reset all"
                        @click="resetActiveBeat">
                        <icon icon-name="trash" color="var(--color-ui-neutral-dark)" />
                    </div>
                    <div
                        class="quick-access-button"
                        :class="{ 'unclickable': !saveDirty }"
                        :title="saveDirty ? 'Save all changes' : 'No unsaved changes'"
                        @click="save('localStorage')">
                        <icon icon-name="save" color="var(--color-ui-neutral-dark)" />
                    </div>
                    <div
                        class="quick-access-button"
                        title="Save current beat to file"
                        @click="saveCurrentBeatToFile">
                        <icon icon-name="download" color="var(--color-ui-neutral-dark)" />
                    </div>
                    <div
                        class="quick-access-button"
                        title="Save current beat to file"
                        @click="uploadDialog?.showModal()">
                        <icon icon-name="upload" color="var(--color-ui-neutral-dark)" />
                    </div>
                </div>
                <toolbox class="toolbox" />
            </div> 
        </div>

        <div class="beat-stage-container">
            <div class="beat-stage">
                <beat-view 
                    :beat-index="activeBeatIndex"
                    :orientation="currentOrientation" />
            </div>
        </div>
        <dialog ref="uploadDialog" class="upload-dialog">
            <h2>Upload a Drum Slayer file</h2>
            <input id="upload-file" type="file" @change="onFileInputChange">
            <button @click="onUpload" :disabled="!canUpload">Upload</button>
            <button @click="uploadDialog?.close()">Cancel</button>
        </dialog>
    </div>
</template>

<script setup lang="ts">
    import { onBeforeUnmount, onMounted, ref, watch } from "vue";
    import BeatSettings from "@/ui/BeatSettings/BeatSettings.vue";
    import BeatView from "@/ui/Beat/Beat.vue";
    import Icon from "@/ui/Widgets/Icon/Icon.vue";
    import Toolbox from "@/ui/Root/Toolbox.vue";
    import { useBeatStore } from "@/BeatStore";
    import { useAppStateStore } from "@/AppState";
    import Draggable from "vuedraggable";

    const TITLE = 'Drum Slayer';

    defineProps<{
        title: string,
    }>();

    const currentOrientation = ref<'horizontal' | 'vertical'>('horizontal');
    const sidebarActive = ref(false);

    const appStateStore = useAppStateStore();
    const beatStore = useBeatStore();    

    window.drumslayer = {
        appState: appStateStore,
        beatStore,
    };

    const {
        save,
        resetActiveBeat,
        activeBeatIndex,
        activeBeat,
        beats,
        addNewBeat,
        bakeAll,
        saveDirty,
        removeBeat,
    } = beatStore;

    function onAddNewBeat() {
        activeBeatIndex.value = addNewBeat();
    }

    let lastActiveBeatIndex: number | null = null;
    function onStartDragBeatTab() {
        lastActiveBeatIndex = activeBeat.value?.id ?? null;
    }
    function onEndDragBeatTab() {
        if (lastActiveBeatIndex !== null) {
            activeBeatIndex.value = beats.value.findIndex(beat => beat.id === lastActiveBeatIndex) ?? lastActiveBeatIndex;
        }
    }

    function onDeleteBeat(index: number) {
        const beatToDelete = beats.value[index];
        if (beatToDelete) {
            if (confirm('ARE YOU SURE?')) {
                removeBeat(index);
            }
        }
    }

    const uploadErr = ref(false);
    const canUpload = ref(false);
    const uploadDialog = ref<HTMLDialogElement | null>(null);
    
    function onFileInputChange(event: Event) {
        const inputEl = event.currentTarget as HTMLInputElement;
        canUpload.value = !!inputEl?.files?.length;
    }

    async function onUpload() {
        const input = document.getElementById('upload-file') as HTMLInputElement;
        if (input.files) {
            const file = input.files.item(0);
            const text = await file?.text() ?? null;
            if (text) {
                try {
                    const parsed = JSON.parse(text);
                    const newBeatIndex = addNewBeat(parsed);
                    if (newBeatIndex === -1) {
                        uploadErr.value = true;
                    }
                } catch (e) {
                    
                }
            }
        }
        uploadDialog.value?.close();
    }

    function saveCurrentBeatToFile() {
        if (activeBeat.value) {
            const serial = activeBeat.value.serialise();
            const a = document.createElement("a");
            const file = new Blob([JSON.stringify(serial)], { type: 'text' });
            a.href = URL.createObjectURL(file);
            a.download = `${ activeBeat.value.name.value }.drms`;
            a.click();
        }
    }

    watch(saveDirty, (dirty) => {
        if (dirty) {
            document.title = `${ TITLE } (unsaved changes)`;
        } else {
            document.title = TITLE;
        }
    });

    const mediaQueryList = window.matchMedia("screen and (max-width: 900px)");
    function onMediaChange(event: MediaQueryListEvent | MediaQueryList) { 
        sidebarActive.value = event.matches;
    }
    mediaQueryList.addEventListener('change', onMediaChange);
    onMediaChange(mediaQueryList);

    function windowMouseUp() {
        appStateStore.selectingUnits.value = false;        
        appStateStore.deselectingUnits.value = false;        
        appStateStore.unitMouseStart.value = null;        
    }

    onMounted(() => {
        window.addEventListener('mouseup', windowMouseUp);
    });

    onBeforeUnmount(() => {
        window.removeEventListener('mouseup', windowMouseUp);
    });

    function toggleOrientation(): void {
        if (currentOrientation.value === "vertical") {
            currentOrientation.value = "horizontal";
        } else {
            currentOrientation.value = "vertical";
        }
    }
</script>

<style scoped lang="scss">
    .root {
        position: relative;
        overflow: hidden;
        color: var(--color-p-light);
        background-color: var(--color-bg-dark);
        height: 100vh;
        align-content: center;

        .sidebar {
            position: absolute;
            left: -28em;
            width: 30em;
            height: 100vh;
            display: flex;
            transition: left 400ms;
            top: 0;
        }
    
        &.sidebar-visible {
            .beat-stage {
                max-width: calc(100vw - 30em);
            }

            .beat-stage-container {
                left: 30em;
                width: calc(100vw - 30em);
            }

            .sidebar {
                left: 0;
            }
        }

        .settings {
            z-index: 1;
            width: 28em;
            background-color: var(--color-bg-light);
            overflow: scroll;
            display: inline-block;

            .title {
                color: var(--color-title-light);
                text-align: center;
            }
        }

        .sidebar-toggle {
            z-index: 1;
            height: 100vh;
            min-width: 2em;
            background-color: var(--color-bg-light);
            left: 0;
            display: flex;
            flex-direction: column;

            .buttons {
                flex: 1;

                .quick-access-button {
                    flex: 1;
                    right: 0;
                    width: 2em;
                    height: 2em;
                    cursor: pointer;
                    margin-bottom: 0.5em;

                    &.unclickable {
                        opacity: 50%;
                        cursor: auto;
                    }
                }
            }

            .toolbox {
                width: 2em;
            }
        }

        .beat-stage-container {
            position: absolute;
            height: 100%;
            left: 0;
            top: 0;
            width: 100vw;
            display: flex;
            flex-direction: column;
            transition: left 400ms, width 400ms;
        }

        .beat-stage {
            position: relative;
            max-height: 100vh;
            margin: auto;
            max-width: 100vw;
            transition: max-width 400ms;
            padding-left: 3em;
        }

        &.vertical-mode {
            .beat-stage {
                margin: auto auto;
                height: 100vh;
            }

            .beat-stage-container {
                display: block;
            }
        }

        .sidebar-left-strip {
            writing-mode: vertical-rl;
            background-color: var(--color-bg-medium);
            > * {
                display: inline-block;
            }
        }

        .sidebar-left-tab, .tab-add {
            display: inline-block;
            width: 100%;
            padding: 8px 3px 24px 3px;
            position: relative;

            .unsaved {
                margin-bottom: 5px;
                opacity: 50%;
            }

            .delete {
                position: absolute;
                bottom: 5px;
                left: 6px;
                width: 15px;
                height: 15px;
                display: inline-block;
                color: var(--color-ui-neutral-dark);
                border-radius: 2px;
                cursor: pointer;

                &:hover {
                    filter: brightness(1.5);
                }

                .x {
                    position: absolute;
                    right: -3px;
                    bottom: -3px;
                }
            }

            &.active {
                background-color: var(--color-bg-light);
                display: inline-block;
            }

            &:hover:not(.active) {
                cursor: pointer;
                background-color: var(--color-ui-neutral-dark);
                transition: background-color 200ms;
            }

            &:hover {
                .delete {
                    filter: brightness(1.2);
                }
            }
        }

        .tab-name {
            display: inline-block;
        }

        @media screen and (max-width: 900px) {
            &.sidebar-visible .sidebar {
                left: 0;
                width: 100vw;
            }
            .sidebar {
                left: calc(-100vw + 2em);
                width: 100vw;
            }
            .settings {
                width: calc(100vw - 2em);
            }
            .sidebar-visible .beat-stage-container {
                left: 100vw;
            }
            .beat-stage-container {
                left: 0;
            }
            .sidebar-visible .beat-stage {
                max-width: 100vw;
            }
        }

        * {
            user-drag: none;
            user-select: none;
        }
    }

    .upload-dialog {
        z-index: 20;
    }
</style>

