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

const store = useProjectsStore();

const { assets } = useAssets();

const CLICK_RADIUS = 22;

const BUTTONS = {
  prev: {
    position: [36, 100],
    image: assets.projects.bottomScreen.prevPressed,
  },
  quit: {
    position: [88, 156],
    image: assets.projects.bottomScreen.quitPressed,
  },
  link: {
    position: [168, 156],
    image: assets.projects.bottomScreen.linkPressed,
  },
  next: {
    position: [220, 100],
    image: assets.projects.bottomScreen.nextPressed,
  },
} as const satisfies Record<
  string,
  { position: Point; image: HTMLImageElement }
>;

type ButtonType = keyof typeof BUTTONS;

type ButtonAnimation = {
  type: ButtonType;
  position: Point;
  showButton: boolean;
  showSmallCircle: boolean;
  showBigCircle: boolean;
};

let currentAnimation: ButtonAnimation | null = null;

const circleContains = (
  [cx, cy]: Point,
  [x, y]: Point,
  radius: number,
): boolean => Math.sqrt(Math.pow(x - cx, 2) + Math.pow(y - cy, 2)) < radius;

const startButtonAnimation = (type: ButtonType) => {
  const anim: ButtonAnimation = {
    type,
    position: BUTTONS[type].position,
    showButton: true,
    showSmallCircle: true,
    showBigCircle: false,
  };
  currentAnimation = anim;

  const SMALL_CIRCLE_DURATION = 0.07;
  const BIG_CIRCLE_DURATION = 0.09;
  const POST_DURATION = 0.07;

  gsap
    .timeline()
    .to(anim, { duration: SMALL_CIRCLE_DURATION })
    .call(() => {
      anim.showSmallCircle = false;
      anim.showBigCircle = true;
    })
    .to(anim, { duration: BIG_CIRCLE_DURATION })
    .call(() => {
      anim.showBigCircle = false;
    })
    .to(anim, { duration: POST_DURATION })
    .call(() => {
      currentAnimation = null;
    });
};

useScreenClick((x, y) => {
  if (currentAnimation) return;

  const project = store.projects[store.currentProject];
  if (circleContains(BUTTONS.prev.position, [x, y], CLICK_RADIUS)) {
    startButtonAnimation("prev");
    store.scrollProjects("left");
  } else if (circleContains(BUTTONS.next.position, [x, y], CLICK_RADIUS)) {
    startButtonAnimation("next");
    store.scrollProjects("right");
  } else if (circleContains(BUTTONS.quit.position, [x, y], CLICK_RADIUS)) {
    startButtonAnimation("quit");
    store.animateOutro();
  } else if (
    circleContains(BUTTONS.link.position, [x, y], CLICK_RADIUS) &&
    project?.link
  ) {
    startButtonAnimation("link");
    // TODO: show confirmation popup before opening the link, like "you are about to navigate to [...]"
    // store.visitProject();
  }
});

useRender((ctx) => {
  if (currentAnimation?.showButton) {
    const image = BUTTONS[currentAnimation.type].image;
    ctx.drawImage(
      image!,
      currentAnimation.position[0] - 14,
      currentAnimation.position[1] - 14,
    );
  }

  if (currentAnimation?.showSmallCircle) {
    ctx.drawImage(
      assets.projects.bottomScreen.circleSmall,
      currentAnimation.position[0] - 28,
      currentAnimation.position[1] - 28,
    );
  }

  if (currentAnimation?.showBigCircle) {
    ctx.drawImage(
      assets.projects.bottomScreen.circleBig,
      currentAnimation.position[0] - 44,
      currentAnimation.position[1] - 44,
    );
  }

  ctx.fillStyle = `rgba(0, 0, 0, ${store.isIntro ? store.intro.fadeOpacity : store.isOutro ? store.outro.fadeOpacity : 0})`;
  ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
});
useKeyDown((key) => {
  if (currentAnimation) return;
  switch (key) {
    case "NDS_LEFT":
      startButtonAnimation("prev");
      store.scrollProjects("left");
      break;
    case "NDS_RIGHT":
      startButtonAnimation("next");
      store.scrollProjects("right");
      break;
  }
});

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