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

const { onRender, onMouseDown } = useScreen();

const store = useProjectsStore();
const { assets } = useAssets();

const CLICK_RADIUS = 22;

const BUTTONS = {
  prev: {
    position: [36, 100],
    image: assets.images.projects.bottomScreen.prevPressed,
  },
  quit: {
    position: [88, 156],
    image: assets.images.projects.bottomScreen.quitPressed,
  },
  link: {
    position: [168, 156],
    image: assets.images.projects.bottomScreen.linkPressed,
  },
  next: {
    position: [220, 100],
    image: assets.images.projects.bottomScreen.nextPressed,
  },
} as const satisfies Record<
  string,
  {
    position: Point;
    image: {
      draw: (ctx: CanvasRenderingContext2D, x: number, y: number) => void;
    };
  }
>;

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

onMouseDown((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),
    );
  }
});

const DOT_SIZE = 3;
const DOT_GAP = 5;
const SCROLLBAR_Y = 8;

onRender((ctx) => {
  const projectsCount = store.projects.length;
  const step = DOT_SIZE + DOT_GAP;
  const totalWidth = projectsCount * DOT_SIZE + (projectsCount - 1) * DOT_GAP;
  const startX = Math.floor((LOGICAL_WIDTH - totalWidth) / 2);

  for (let i = 0; i < projectsCount; i++) {
    const x = startX + i * step;

    if (i === store.currentProject) {
      ctx.fillStyle = "#304961";
      ctx.fillRect(x - 1, SCROLLBAR_Y - 1, DOT_SIZE + 2, DOT_SIZE + 2);
      ctx.fillStyle = "#f8f8f8";
      ctx.fillRect(x, SCROLLBAR_Y, DOT_SIZE, DOT_SIZE);
    } else {
      ctx.fillStyle = "#4a7898";
      ctx.fillRect(x, SCROLLBAR_Y, DOT_SIZE, DOT_SIZE);
    }
  }

  if (store.currentProject === 0) {
    assets.images.projects.bottomScreen.prevDisabled.draw(
      ctx,
      BUTTONS.prev.position[0] - 14,
      BUTTONS.prev.position[1] - 14,
    );
  } else if (store.currentProject === store.projects.length - 1) {
    assets.images.projects.bottomScreen.nextDisabled.draw(
      ctx,
      BUTTONS.next.position[0] - 14,
      BUTTONS.next.position[1] - 14,
    );
  }

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

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

  if (currentAnimation?.showBigCircle) {
    assets.images.projects.bottomScreen.circleBig.draw(
      ctx,
      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, LOGICAL_WIDTH, LOGICAL_HEIGHT);
});

useKeyDown(({ key, repeated }) => {
  if (
    repeated ||
    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_B":
      if (repeated) break;

      startButtonAnimation("quit");
      store.animateOutro();
      break;
    case "NDS_A":
    case "NDS_START":
      if (repeated) break;

      startButtonAnimation("link");
      setTimeout(
        () => (store.showConfirmationPopup = true),
        1000 * (SMALL_CIRCLE_DURATION + BIG_CIRCLE_DURATION + POST_DURATION),
      );
      break;
  }
});

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