<script setup lang="ts">
import OptionsMenu from "./Options/Menu.vue";
import OptionsRenderingMode from "./Options/RenderingMode.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 store = useSettingsStore();
const { assets } = useAssets();
const { onRender } = useScreen();

onRender((ctx) => {
  if (store.submenuBackground.opacity > 0) {
    ctx.globalAlpha = store.submenuBackground.opacity;
    ctx.translate(0, store.submenuBackground.offsetY);
    assets.images.home.topScreen.background.draw(ctx, 0, 0);
  }
});

if (app.previousScreen === "home") {
  store.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, pressed, selectorPosition } = useButtonNavigation({
  buttons: {
    options: [31, 119, 49, 49],
    optionsLanguage: [31, 71, 49, 49],
    options2048: [79, 71, 49, 49],
    optionsRenderingMode: [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: store.selectedButton,
  onActivate: (buttonName) => {
    if (isSubMenu(buttonName)) {
      store.openSubMenu(buttonName);
    } else {
      if (buttonName === "options") select("optionsLanguage");
      if (buttonName === "clock") select("clockAchievements");
      if (buttonName === "user") select("userUserName");
      if (buttonName === "touchScreen") store.openSubMenu("touchScreenTapTap");
    }
  },
  navigation: {
    options: {
      right: "clock",
      up: "optionsLanguage",
    },
    optionsLanguage: {
      down: "options",
      up: "optionsRenderingMode",
      right: "options2048",
    },
    options2048: {
      down: ["options", false],
      left: "optionsLanguage",
      up: ["optionsRenderingMode", false],
    },
    optionsRenderingMode: {
      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 store.currentMenu === parent && store.menuExpanded;
    }
    return true;
  },
  disabled: computed(
    () =>
      store.currentSubMenu !== null ||
      store.submenuTransition.opacity < 1 ||
      store.isIntro ||
      store.isOutro ||
      store.animatingNotification,
  ),
  selectorAnimation: {
    duration: 0.11,
    ease: "none",
  },
});

const isSubmenuSelected = computed(() => isSubMenu(selected.value));

const selectedSubmenuExtraOffsetY = computed(
  () =>
    store.submenuTransition.selectorOffsetY - store.submenuTransition.offsetY,
);

const isAnyOtherMenuOpen = (menu: SettingsMenu) => {
  if (store.currentSubMenu) {
    return !store.currentSubMenu.startsWith(menu);
  }
  if (isSubmenuSelected.value) {
    return getParentMenu(selected.value) !== menu;
  }
  return false;
};

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

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

const viewComponents: Record<string, Component> = {
  optionsRenderingMode: OptionsRenderingMode,
  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, store.menuOffsets[1]);
    case "user":
      return Math.min(0, store.menuOffsets[1] + store.menuOffsets[2]);
    case "touchScreen":
      return Math.min(
        0,
        store.menuOffsets[1] + store.menuOffsets[2] + store.menuOffsets[3],
      );
    default:
      return 0;
  }
});

const selectorTransitionOffsetY = computed(() => {
  if (isSubmenuSelected.value || selected.value === "touchScreen") {
    return store.submenuTransition.selectorOffsetY;
  }
  return store.submenuTransition.offsetY;
});

const handleActivateA = () => {
  if (store.isIntro || store.isOutro || store.submenuTransition.opacity < 1)
    return;

  if (isSubMenu(selected.value)) {
    store.openSubMenu(selected.value);
  } else {
    if (selected.value === "options") select("optionsLanguage");
    if (selected.value === "clock") select("clockAchievements");
    if (selected.value === "user") select("userUserName");
    if (selected.value === "touchScreen")
      store.openSubMenu("touchScreenTapTap");
  }
};

const handleActivateB = () => {
  if (store.isIntro || store.isOutro || store.submenuTransition.opacity < 1)
    return;

  if (isSubmenuSelected.value) {
    select(getParentMenu(selected.value));
  } else {
    store.animateOutro();
  }
};
</script>

<template>
  <template v-if="!store.currentSubMenu">
    <TouchScreenMenu
      :x="
        177 + store.menuOffsets[1] + store.menuOffsets[2] + store.menuOffsets[3]
      "
      :y="
        121 +
        store.menuYOffset +
        (selected === 'touchScreen'
          ? store.submenuTransition.selectorOffsetY
          : store.submenuTransition.offsetY)
      "
      :opacity="store.submenuTransition.opacity"
      :pressed="pressed"
      :is-any-other-menu-open="isAnyOtherMenuOpen('touchScreen')"
    />
    <UserMenu
      :x="129 + store.menuOffsets[1] + store.menuOffsets[2]"
      :y="121 + store.menuYOffset + store.submenuTransition.offsetY"
      :opacity="store.submenuTransition.opacity"
      :pressed="pressed"
      :is-any-other-menu-open="isAnyOtherMenuOpen('user')"
      :submenu-extra-offset-y="selectedSubmenuExtraOffsetY"
    />
    <ClockMenu
      :x="81 + store.menuOffsets[1]"
      :y="121 + store.menuYOffset + store.submenuTransition.offsetY"
      :opacity="store.submenuTransition.opacity"
      :pressed="pressed"
      :is-any-other-menu-open="isAnyOtherMenuOpen('clock')"
      :submenu-extra-offset-y="selectedSubmenuExtraOffsetY"
    />
    <OptionsMenu
      :x="33"
      :y="121 + store.menuYOffset + store.submenuTransition.offsetY"
      :opacity="store.submenuTransition.opacity"
      :pressed="pressed"
      :is-any-other-menu-open="isAnyOtherMenuOpen('options')"
      :submenu-extra-offset-y="selectedSubmenuExtraOffsetY"
    />

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

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