<script setup lang="ts">
import OptionsMenu from "./Options/Menu.vue";
import OptionsStartUp from "./Options/StartUp.vue";
import OptionsLanguage from "./Options/Language.vue";
import Options2048 from "./Options/2048.vue";

import UserMenu from "./User/Menu.vue";
import UserColor from "./User/Color.vue";
import UserBirthday from "./User/Birthday.vue";
import UserUserName from "./User/UserName.vue";
import UserSnake from "./User/Snake.vue";

import ClockMenu from "./Clock/Menu.vue";
import ClockAchievements from "./Clock/Achievements.vue";
import ClockDate from "./Clock/Date.vue";
import ClockTime from "./Clock/Time.vue";
import TouchScreenMenu from "./TouchScreen/Menu.vue";
import TouchScreenTapTap from "./TouchScreen/TapTap.vue";
import Selector from "~/components/Common/ButtonSelector.vue";

const app = useAppStore();
const settingsStore = useSettingsStore();

if (app.previousScreen === "home") {
  settingsStore.selectedButton = "options";
}

const isMainMenu = (button: string): button is SettingsMenu =>
  SETTINGS_MENUS.includes(button as SettingsMenu);

const isSubMenu = (button: string): button is SettingsSubMenu =>
  SETTINGS_SUB_MENUS.includes(button as SettingsSubMenu);

const getParentMenu = (submenu: string): SettingsMenu => {
  const match = submenu.match(/^(options|clock|user|touchScreen)/);
  if (!match?.[1]) throw new Error(`Invalid submenu: '${submenu}'`);
  return match[1] as SettingsMenu;
};

const { select, selected, selectorPosition } = useButtonNavigation({
  buttons: {
    options: [31, 119, 49, 49],
    optionsLanguage: [31, 71, 49, 49],
    options2048: [79, 71, 49, 49],
    optionsStartUp: [31, 23, 49, 49],

    clock: [79, 119, 49, 49],
    clockAchievements: [79, 71, 49, 49],
    clockTime: [127, 71, 49, 49],
    clockDate: [79, 23, 49, 49],

    user: [127, 119, 49, 49],
    userBirthday: [79, 71, 49, 49],
    userUserName: [127, 71, 49, 49],
    userSnake: [175, 71, 49, 49],
    userColor: [127, 23, 49, 49],

    touchScreen: [175, 119, 49, 49],
  },
  initialButton: settingsStore.selectedButton,
  onButtonClick: (buttonName) => {
    if (isSubMenu(buttonName)) {
      settingsStore.openSubMenu(buttonName);
    } else {
      if (buttonName === "options") select("optionsLanguage");
      if (buttonName === "clock") select("clockAchievements");
      if (buttonName === "user") select("userUserName");
      if (buttonName === "touchScreen")
        settingsStore.openSubMenu("touchScreenTapTap");
    }
  },
  navigation: {
    options: {
      right: "clock",
      up: "optionsLanguage",
    },
    optionsLanguage: {
      down: "options",
      up: "optionsStartUp",
      right: "options2048",
    },
    options2048: {
      down: ["options", false],
      left: "optionsLanguage",
      up: ["optionsStartUp", false],
    },
    optionsStartUp: {
      right: ["options2048", false],
      down: "optionsLanguage",
    },

    clock: {
      left: "options",
      right: "user",
      up: "clockAchievements",
    },
    clockAchievements: {
      down: "clock",
      up: "clockDate",
      right: "clockTime",
    },
    clockTime: {
      down: ["clock", false],
      left: "clockAchievements",
      up: ["clockDate", false],
    },
    clockDate: {
      right: ["clockTime", false],
      down: "clockAchievements",
    },

    user: {
      left: "clock",
      right: "touchScreen",
      up: "userUserName",
    },
    userBirthday: {
      down: ["user", false],
      up: ["userColor", false],
      right: "userUserName",
    },
    userUserName: {
      down: "user",
      left: "userBirthday",
      right: "userSnake",
      up: "userColor",
    },
    userSnake: {
      down: ["user", false],
      left: "userUserName",
      up: ["userColor", false],
    },
    userColor: {
      left: ["userBirthday", false],
      right: ["userSnake", false],
      down: "userUserName",
    },

    touchScreen: {
      left: "user",
    },
  },
  canClickButton: (buttonName) => {
    if (isSubMenu(buttonName)) {
      const parent = getParentMenu(buttonName);
      return settingsStore.currentMenu === parent && settingsStore.menuExpanded;
    }
    return true;
  },
  disabled: computed(
    () =>
      settingsStore.currentSubMenu !== null ||
      settingsStore.isIntro ||
      settingsStore.isOutro ||
      settingsStore.animatingNotification,
  ),
  selectorAnimation: {
    duration: 0.11,
    ease: "none",
  },
});

const isSubmenuSelected = computed(() => isSubMenu(selected.value));
const selectedSubmenuParent = computed(() =>
  isSubmenuSelected.value ? getParentMenu(selected.value) : null,
);

provide("menusContext", {
  isSubmenuSelected,
  selectedSubmenuParent,
});

watch(
  selected,
  (newSelected) => {
    settingsStore.selectedButton = newSelected;

    if (settingsStore.currentSubMenu === null) {
      if (isMainMenu(newSelected)) {
        settingsStore.openMenu(newSelected, false);
      } else if (isSubMenu(newSelected)) {
        const parentMenu = getParentMenu(newSelected);
        if (parentMenu) {
          settingsStore.openMenu(parentMenu, true);
        }
      }
    }
  },
  { immediate: true },
);

const viewComponents: Record<string, Component> = {
  optionsStartUp: OptionsStartUp,
  optionsLanguage: OptionsLanguage,
  options2048: Options2048,

  clockAchievements: ClockAchievements,
  clockDate: ClockDate,
  clockTime: ClockTime,

  userColor: UserColor,
  userBirthday: UserBirthday,
  userUserName: UserUserName,
  userSnake: UserSnake,

  touchScreenTapTap: TouchScreenTapTap,
};

const selectorXOffset = computed(() => {
  const menu = isMainMenu(selected.value)
    ? selected.value
    : getParentMenu(selected.value);

  switch (menu) {
    case "clock":
      return Math.min(0, settingsStore.menuOffsets[1]);
    case "user":
      return Math.min(
        0,
        settingsStore.menuOffsets[1] + settingsStore.menuOffsets[2],
      );
    case "touchScreen":
      return Math.min(
        0,
        settingsStore.menuOffsets[1] +
          settingsStore.menuOffsets[2] +
          settingsStore.menuOffsets[3],
      );
    default:
      return 0;
  }
});

const handleActivateB = () => {
  if (settingsStore.isIntro || settingsStore.isOutro) return;
  settingsStore.animateOutro();
};

const handleActivateA = () => {
  if (settingsStore.isIntro || settingsStore.isOutro) return;
  select(getParentMenu(selected.value));
};
</script>

<template>
  <template v-if="!settingsStore.currentSubMenu">
    <TouchScreenMenu
      :x="
        177 +
        settingsStore.menuOffsets[1] +
        settingsStore.menuOffsets[2] +
        settingsStore.menuOffsets[3]
      "
      :y="121 + settingsStore.menuYOffset"
      :opacity="1"
    />
    <UserMenu
      :x="129 + settingsStore.menuOffsets[1] + settingsStore.menuOffsets[2]"
      :y="121 + settingsStore.menuYOffset"
    />
    <ClockMenu
      :x="81 + settingsStore.menuOffsets[1]"
      :y="121 + settingsStore.menuYOffset"
    />
    <OptionsMenu :x="33" :y="121 + settingsStore.menuYOffset" />

    <Selector
      :rect="[
        selectorPosition[0] + selectorXOffset,
        selectorPosition[1] + settingsStore.menuYOffset,
        selectorPosition[2],
        selectorPosition[3],
      ]"
      :opacity="1"
    />

    <CommonButtons
      v-if="isSubmenuSelected"
      :y-offset="settingsStore.barOffsetY"
      :b-label="$t('common.goBack')"
      :a-label="$t('common.select')"
      @activate-b="handleActivateA()"
    />
    <CommonButtons
      v-else
      :y-offset="settingsStore.barOffsetY"
      :b-label="$t('common.quit')"
      :a-label="$t('common.select')"
      @activate-b="handleActivateB()"
    />
  </template>
  <component :is="viewComponents[settingsStore.currentSubMenu]" v-else />
</template>
