<script setup lang="ts">
import gsap from "gsap";
import type { Achievement } from "~/stores/achievements";

const { onRender } = useScreen();
const achievements = useAchievementsStore();
const { assets } = useAssets();

const queue = ref<Achievement[]>([]);
const currentAchievement = ref<Achievement | null>(null);
const x = ref(LOGICAL_WIDTH);
const isAnimating = ref(false);

const PADDING = 4;
const LOGO_SIZE = assets.images.achievements.notificationLogo.rect.height;
const NOTIF_WIDTH = 120;
const NOTIF_HEIGHT = LOGO_SIZE + PADDING * 2;
const NOTIF_Y = 3;
const NOTIF_X_VISIBLE = LOGICAL_WIDTH - NOTIF_WIDTH;
const TEXT_X_OFFSET = LOGO_SIZE + PADDING * 2;
const LINE_HEIGHT = 8;

achievements.$onAction(({ name, args, after }) => {
  if (name === "unlock") {
    after((wasUnlocked) => {
      if (wasUnlocked) {
        queue.value.push(args[0]);
        processQueue();
      }
    });
  }
});

const processQueue = () => {
  if (isAnimating.value || queue.value.length === 0) return;

  const next = queue.value.shift();
  if (!next) return;

  currentAchievement.value = next;
  isAnimating.value = true;

  gsap
    .timeline()
    .to(x, {
      value: NOTIF_X_VISIBLE,
      duration: 0.3,
      ease: "power2.out",
    })
    .to(
      x,
      {
        value: LOGICAL_WIDTH,
        duration: 0.3,
        ease: "power2.in",
      },
      "+=2.5",
    )
    .call(() => {
      currentAchievement.value = null;
      isAnimating.value = false;
      processQueue();
    });
};

onRender((ctx) => {
  if (!currentAchievement.value) return;

  const logo = assets.images.achievements.notificationLogo;

  // shadow
  ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
  ctx.fillRect(x.value + 1, NOTIF_Y + 1, NOTIF_WIDTH, NOTIF_HEIGHT);

  // border
  ctx.fillStyle = "#282828";
  ctx.fillRect(x.value, NOTIF_Y, NOTIF_WIDTH, 1); // Top
  ctx.fillRect(x.value, NOTIF_Y, 1, NOTIF_HEIGHT); // Left
  ctx.fillRect(x.value, NOTIF_Y + NOTIF_HEIGHT - 1, NOTIF_WIDTH, 1); // Bottom

  // background
  ctx.fillStyle = "#fafafa";
  ctx.fillRect(x.value + 1, NOTIF_Y + 1, NOTIF_WIDTH - 1, NOTIF_HEIGHT - 2);

  // logo
  logo.draw(ctx, x.value + PADDING, NOTIF_Y + PADDING);

  // text (1 or 2 lines)
  ctx.font = "7px NDS7";
  ctx.textBaseline = "top";
  ctx.fillStyle = "#282828";

  const lines = $t(`achievements.${currentAchievement.value}`).split("\n");
  const textY =
    lines.length === 1 ? NOTIF_Y + PADDING + 4 : NOTIF_Y + PADDING + 1;

  for (let i = 0; i < lines.length; i++) {
    ctx.fillText(lines[i]!, x.value + TEXT_X_OFFSET, textY + i * LINE_HEIGHT);
  }
}, 200);

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