<script setup lang="ts">
import gsap from "gsap";

const { locales, locale, setLocale } = useI18n();
const store = useSettingsStore();
const confirmationModal = useConfirmationModal();
const achievements = useAchievementsStore();
const { assets } = useAssets();
const { onRender } = useScreen();

const BUTTON_KEYS = [
  "english",
  "german",
  "french",
  "spanish",
  "italian",
  "japanese",
] as const;

const BUTTON_POSITIONS = [
  [15, 32],
  [143, 32],
  [15, 80],
  [143, 80],
  [15, 128],
  [143, 128],
] as const;

const isAnimating = ref(true);

const { selected, selectorPosition } = useButtonNavigation({
  buttons: {
    english: [10, 27, 106, 41],
    german: [138, 27, 106, 41],
    french: [10, 75, 106, 41],
    spanish: [138, 75, 106, 41],
    italian: [10, 123, 106, 41],
    japanese: [138, 123, 106, 41],
  },
  initialButton:
    BUTTON_KEYS[locales.value.findIndex((l) => l.code === locale.value)] ??
    BUTTON_KEYS[0]!,
  onActivate: () => handleActivateA(),
  navigation: {
    english: {
      right: "german",
      down: "french",
    },
    german: {
      left: "english",
      down: "spanish",
    },
    french: {
      up: "english",
      right: "spanish",
      down: "italian",
    },
    spanish: {
      up: "german",
      left: "french",
      down: "japanese",
    },
    italian: {
      up: "french",
      right: "japanese",
    },
    japanese: {
      up: "spanish",
      left: "italian",
    },
  },
  disabled: isAnimating,
  selectorAnimation: {
    duration: 0.1,
    ease: "power2.out",
  },
});

const SLIDE_OFFSET = 48;
const SLIDE_DURATION = 0.15;
const OUTRO_OFFSET = 96;
const OUTRO_DURATION = 0.25;
const ROW_STAGGER = SLIDE_DURATION + 0.075;
const ROW_COUNT = 3;

const selectedRow = computed(() => {
  const index = BUTTON_KEYS.indexOf(selected.value);
  return Math.floor(index / 2);
});

const animation = reactive({
  rowOffsetY: Array(ROW_COUNT).fill(SLIDE_OFFSET) as number[],
  rowOpacity: Array(ROW_COUNT).fill(0) as number[],
});

const animateIntro = async () => {
  isAnimating.value = true;
  const timeline = gsap.timeline();
  for (let i = 0; i < ROW_COUNT; i++) {
    timeline
      .to(
        animation.rowOffsetY,
        { [i]: 0, duration: SLIDE_DURATION, ease: "none" },
        i * ROW_STAGGER,
      )
      .to(
        animation.rowOpacity,
        { [i]: 1, duration: SLIDE_DURATION, ease: "none" },
        i * ROW_STAGGER,
      );
  }
  await timeline;
  isAnimating.value = false;
};

const animateOutro = async () => {
  isAnimating.value = true;
  const timeline = gsap.timeline();
  for (let i = 0; i < ROW_COUNT; i++) {
    timeline
      .to(
        animation.rowOffsetY,
        { [i]: OUTRO_OFFSET, duration: OUTRO_DURATION, ease: "none" },
        0,
      )
      .to(
        animation.rowOpacity,
        { [i]: 0, duration: OUTRO_DURATION, ease: "none" },
        0,
      );
  }
  await timeline;
};

onMounted(() => {
  animateIntro();
});

const handleActivateB = async () => {
  if (isAnimating.value) return;
  await animateOutro();
  store.closeSubMenu();
};

const handleActivateA = () => {
  if (isAnimating.value) return;
  const selectedLocale = locales.value[BUTTON_KEYS.indexOf(selected.value)]!;

  setLocale(selectedLocale.code);

  if (!achievements.advancement.languages.includes(selectedLocale.code)) {
    achievements.advancement.languages.push(selectedLocale.code);
    if (achievements.advancement.languages.length === locales.value.length) {
      achievements.unlock("settings_language_try_all");
    }
  }

  confirmationModal.open({
    text: $t(
      "settings.options.language.confirmation",
      {},
      { locale: selectedLocale.code },
    ),
    onClosed: async () => {
      await animateOutro();
      store.closeSubMenu();
    },
    keepButtonsDown: true,
    timeout: 2000,
  });
};

onRender((ctx) => {
  ctx.font = "10px NDS10";
  ctx.fillStyle = "#010101";

  for (let i = 0; i < locales.value.length; i += 1) {
    const row = Math.floor(i / 2);
    const [x, y] = BUTTON_POSITIONS[i]!;
    const isSelected = selected.value === BUTTON_KEYS[i];
    const buttonImage = isSelected
      ? assets.images.settings.bottomScreen.options.languageButtonActive
      : assets.images.settings.bottomScreen.options.languageButton;

    ctx.save();
    ctx.globalAlpha = animation.rowOpacity[row]!;
    ctx.translate(0, animation.rowOffsetY[row]!);

    buttonImage.draw(ctx, x, y, isSelected ? { colored: true } : undefined);
    const name = locales.value[i]?.name;
    if (!name) {
      throw new Error(`Missing locale or locale name: ${BUTTON_KEYS[i]}`);
    }
    fillTextHCentered(ctx, name, x, y + 20, 96);

    ctx.restore();
  }
});

defineOptions({
  render: () => null,
});
</script>

<template>
  <CommonButtons
    :y-offset="confirmationModal.buttonsYOffset + store.submenuButtonsOffsetY"
    :b-label="$t('common.cancel')"
    :a-label="$t('common.confirm')"
    @activate-b="handleActivateB"
  />

  <CommonButtonSelector
    :rect="[
      selectorPosition[0],
      selectorPosition[1] + animation.rowOffsetY[selectedRow]!,
      selectorPosition[2],
      selectorPosition[3],
    ]"
    :opacity="animation.rowOpacity[selectedRow]!"
  />
</template>
