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

const { onRender, onClick } = useScreen();

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 SMALL_CIRCLE_DURATION = 0.07;
const BIG_CIRCLE_DURATION = 0.09;
const POST_DURATION = 0.07;

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

  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;
    });
};

onClick((x, y) => {
  if (
    currentAnimation ||
    store.isIntro ||
    store.isOutro ||
    store.showConfirmationPopup
  )
    return;

  if (
    circleContains(BUTTONS.prev.position, [x, y], CLICK_RADIUS) &&
    store.currentProject > 0
  ) {
    startButtonAnimation("prev");
    store.scrollProjects("left");
  } else if (
    circleContains(BUTTONS.next.position, [x, y], CLICK_RADIUS) &&
    store.currentProject < store.projects.length - 1
  ) {
    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)) {
    startButtonAnimation("link");
    setTimeout(
      () => (store.showConfirmationPopup = true),
      1000 * (SMALL_CIRCLE_DURATION + BIG_CIRCLE_DURATION + POST_DURATION),
    );
  }
});

onRender((ctx) => {
  // Draw disabled buttons
  if (store.currentProject === 0) {
    ctx.drawImage(
      assets.projects.bottomScreen.prevDisabled,
      BUTTONS.prev.position[0] - 14,
      BUTTONS.prev.position[1] - 14,
    );
  }
  if (store.currentProject === store.projects.length - 1) {
    ctx.drawImage(
      assets.projects.bottomScreen.nextDisabled,
      BUTTONS.next.position[0] - 14,
      BUTTONS.next.position[1] - 14,
    );
  }

  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 ||
    store.isIntro ||
    store.isOutro ||
    store.showConfirmationPopup
  )
    return;

  switch (key) {
    case "NDS_LEFT":
      if (store.currentProject > 0) {
        startButtonAnimation("prev");
        store.scrollProjects("left");
      }
      break;
    case "NDS_RIGHT":
      if (store.currentProject < store.projects.length - 1) {
        startButtonAnimation("next");
        store.scrollProjects("right");
      }
      break;
    case "NDS_A":
    case "NDS_START":
      startButtonAnimation("link");
      setTimeout(
        () => (store.showConfirmationPopup = true),
        1000 * (SMALL_CIRCLE_DURATION + BIG_CIRCLE_DURATION + POST_DURATION),
      );
      break;
  }
});

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