<script setup lang="ts">
import { SettingsBottomScreenNumberInput as NumberInput } from "#components";
import { ICONS } from "~/utils/icons";
import gsap from "gsap";

const APP_COLOR_TO_FONT_COLOR: Record<string, string> = {
  "#61829a": "#fbfbfb", // cyan
  "#ba4900": "#fbe3d3", // maroon
  "#fb0018": "#fbcbd3", // red
  "#fb8afb": "#fbebfb", // pink
  "#fb9200": "#fbf3e3", // orange
  "#f3e300": "#fbfbdb", // yellow
  "#aafb00": "#fbfbfb", // lime
  "#00fb00": "#fbfbfb", // green
  "#00a238": "#fbfbfb", // dark green
  "#49db8a": "#ebfbf3", // duck
  "#30baf3": "#fbfbfb", // light blue
  "#0059f3": "#dbebfb", // blue
  "#000092": "#ebebfb", // dark blue
  "#8a00d3": "#f3dbfb", // purple
  "#d300eb": "#fbfbfb", // magenta
  "#fb0092": "#ebe3f3", // fuschia
};

const { assets } = useAssets();
const achievementAssets =
  assets.images.settings.bottomScreen.clock.achievements;
const { onRender, onClick } = useScreen();

const app = useAppStore();
const store = useSettingsStore();
const achievements = useAchievementsStore();
const achievementsScreen = useAchievementsScreen();
const confirmationModal = useConfirmationModal();

const isAnimating = ref(true);

const bLabel = ref($t("common.goBack"));
const aLabel = ref($t("common.select"));

const SLIDE_OFFSET = 96;
const SLIDE_DURATION = 0.25;
const ARROW_SLIDE_DELAY = 0.15;
const ARROW_SLIDE_DURATION = 0.167;
const VIEW_ALL_OFFSET = -20;

const animation = reactive({
  offsetY: SLIDE_OFFSET,
  opacity: 0,
  viewAllOffsetY: VIEW_ALL_OFFSET,
});

const obtainedRef =
  useTemplateRef<InstanceType<typeof NumberInput>>("obtained");
const totalRef = useTemplateRef<InstanceType<typeof NumberInput>>("total");

const animateIntro = async () => {
  isAnimating.value = true;
  await Promise.all([
    obtainedRef.value?.animateIntro(),
    totalRef.value?.animateIntro(),
    gsap
      .timeline()
      .to(animation, { offsetY: 0, duration: SLIDE_DURATION, ease: "none" }, 0)
      .to(animation, { opacity: 1, duration: SLIDE_DURATION, ease: "none" }, 0)
      .call(
        () => {
          bLabel.value = $t("common.cancel");
          aLabel.value = $t("common.reset");
        },
        [],
        SUBMENU_LABEL_CHANGE_DELAY,
      )
      .to(
        animation,
        { viewAllOffsetY: 0, duration: ARROW_SLIDE_DURATION, ease: "none" },
        SLIDE_DURATION + ARROW_SLIDE_DELAY,
      ),
  ]);
  isAnimating.value = false;
};

const animateOutro = async () => {
  isAnimating.value = true;
  await Promise.all([
    obtainedRef.value?.animateOutro(),
    totalRef.value?.animateOutro(),
    gsap
      .timeline()
      .to(
        animation,
        {
          viewAllOffsetY: VIEW_ALL_OFFSET,
          duration: ARROW_SLIDE_DURATION,
          ease: "none",
        },
        0,
      )
      .to(
        animation,
        { offsetY: SLIDE_OFFSET, duration: SLIDE_DURATION, ease: "none" },
        0,
      )
      .to(animation, { opacity: 0, duration: SLIDE_DURATION, ease: "none" }, 0),
  ]);
};

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

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

const handleReset = () => {
  if (isAnimating.value) return;
  confirmationModal.open({
    text: $t("settings.clock.achievements.resetConfirmation"),
    bLabel: $t("common.no"),
    aLabel: $t("common.yes"),
    onClosed: (choice) => {
      if (choice === "A") {
        achievements.reset();
      }
    },
  });
};

const handleVisitAll = () => {
  if (isAnimating.value) return;
  achievementsScreen.animateFadeToBlackIntro();
};

onClick((x, y) => {
  if (isAnimating.value) return;
  const viewAllRect = achievementAssets.viewAllButton.rect;
  if (rectContains([127, 2, viewAllRect.width, viewAllRect.height], [x, y])) {
    handleVisitAll();
  }
});

useKeyDown(({ key }) => {
  if (isAnimating.value) return;
  if (key === "NDS_X") {
    handleVisitAll();
  }
});

onRender((ctx) => {
  // slash divider
  ctx.globalAlpha = animation.opacity;
  ctx.translate(0, animation.offsetY);
  ctx.textBaseline = "top";
  ctx.fillStyle = "#515151";
  ctx.fillRect(7 * 16 - 1, 4 * 16 - 1, 16 * 3 + 1, 16 * 3 + 1);
  ctx.fillStyle = achievements.allObtained ? app.color.hex : "#797979";
  ctx.fillRect(7 * 16, 4 * 16, 16 * 3 - 1, 16 * 3 - 1);
  ctx.font = "39px NDS39";
  ctx.letterSpacing = "2px";
  ctx.fillStyle = achievements.allObtained
    ? APP_COLOR_TO_FONT_COLOR[app.color.hex]!
    : "#fbfbfb";
  ctx.fillText("/", 7 * 16 + 3, 4 * 16 + 4);
});

onRender((ctx) => {
  ctx.translate(0, animation.viewAllOffsetY);

  achievementAssets.viewAllButton.draw(ctx, 127, 2);
  achievementAssets.smallTrophy.draw(ctx, 131, 6);

  ctx.font = "10px NDS10";
  ctx.textBaseline = "top";
  ctx.fillStyle = "#010101";

  const label = `${ICONS.X} ${$t("settings.clock.achievements.viewAll")}`;
  fillTextHCentered(
    ctx,
    label,
    145,
    7,
    achievementAssets.viewAllButton.rect.width - 18,
  );
}, 1000);
</script>

<template>
  <NumberInput
    ref="obtained"
    :model-value="achievements.unlocked.length"
    :title="$t('settings.clock.achievements.obtained')"
    :x="4 * 16 - 1"
    :selected="achievements.allObtained"
    :disabled="true"
  />

  <NumberInput
    ref="total"
    :model-value="ACHIEVEMENTS.length"
    :title="$t('settings.clock.achievements.total')"
    :x="9 * 16 - 1"
    :selected="achievements.allObtained"
    :disabled="true"
  />

  <CommonButtons
    :y-offset="confirmationModal.buttonsYOffset + store.submenuButtonsOffsetY"
    :b-label="bLabel"
    :a-label="aLabel"
    @activate-b="handleActivateB()"
    @activate-a="handleReset()"
  />
</template>
