import { clamp } from 'lodash-es';

import { CanvasRegion } from '@/components/edit2025/canvasRenderer/CanvasRenderer';

import { StudioContextType } from '../StudioContext';
import focusTimeline from '../actions/focusTimeline';
import { getSongEndBeats, getSongStartBeats } from '../selectors';
import { RULER_HEIGHT } from './makeStudioBeatGridRegion';
import { SCROLLBAR_HEIGHT } from './makeStudioScrollbarRegions';

export default function makePlayheadRegion(
  studioContext: StudioContextType
): CanvasRegion {
  const { playbackController, timelineController } = studioContext;

  const playheadBeats = playbackController.getCurrentBeats();

  const playheadY = 10;
  const playheadDiameter = 10;
  const hoveredPlayheadDiameter = 16;
  const timelineWrapperRect = timelineController.getWrapperRect();
  const playheadCenterX =
    studioContext.timelineController.followMode && playbackController.playing
      ? timelineWrapperRect.width / 2
      : studioContext.beatsToCanvasX(playheadBeats);

  const height = timelineWrapperRect.height;

  return {
    touchTarget: {
      bounds: {
        top: playheadY - 5,
        bottom: playheadY + 15,
        left: playheadCenterX - 20 / 2,
        right: playheadCenterX + 20 / 2,
      },
      hoverCursor: 'pointer',
      dragCursor: 'pointer',
      onMouseDown: studioContext.handleClickDrag(() => {
        studioContext.setState(focusTimeline);
        return {
          onMouseMove: ({ moveBeats }) => {
            studioContext.playbackController.seek(
              clamp(
                moveBeats,
                getSongStartBeats(studioContext.state),
                getSongEndBeats(studioContext.state)
              )
            );
            studioContext.timelineController.frameCountRef.current++;
          },
        };
      }),
    },
    renderTop: (ctx: CanvasRenderingContext2D, hovered: boolean) => {
      if (studioContext.previewController.previewingOffTimeline) {
        return;
      }

      if (studioContext.recordingController.isRecording) {
        ctx.fillStyle = '#F24018';
      } else if (studioContext.playbackController.playing || hovered) {
        ctx.fillStyle = 'rgba(255,255,255, 1)';
      } else {
        ctx.fillStyle = 'rgba(255,255,255, 0.25)';
      }
      const effectiveDiameter = hovered
        ? hoveredPlayheadDiameter
        : playheadDiameter;
      const y = playheadY - (effectiveDiameter - playheadDiameter) / 2;

      ctx.fillRect(
        playheadCenterX,
        y + effectiveDiameter + 1,
        1,
        height + effectiveDiameter - (SCROLLBAR_HEIGHT + RULER_HEIGHT)
      );

      ctx.beginPath();
      ctx.roundRect(
        playheadCenterX - effectiveDiameter / 2 + 0.5,
        y + 1,
        effectiveDiameter,
        effectiveDiameter,
        effectiveDiameter / 2
      );
      ctx.closePath();
      ctx.fill();

      if (hovered) {
        ctx.beginPath();
        ctx.fillStyle = 'rgba(28,28,31,0.4)';
        ctx.roundRect(playheadCenterX - 2, y + 4, 4, 10, 2);
        ctx.fill();
      }
    },
  };
}
