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

import { StudioContextType } from '../StudioContext';
import { RULER_HEIGHT } from './makeStudioBeatGridRegion';
import { SCROLLBAR_HEIGHT } from './makeStudioScrollbarRegions';

let contextBeforeBeatsDragDelta = 0;
let contextAfterBeatsDragDelta = 0;
let contextBeforeDragging = false;
let contextAfterDragging = false;

export default function makeStudioContextWindowRegions(
  studioContext: StudioContextType
): CanvasRegion[] {
  const contextWindowStartBeats =
    contextBeforeBeatsDragDelta +
    studioContext.getEffectiveSelection().startBeats -
    studioContext.contextBeforeBeats;

  const contextWindowEndBeats =
    contextAfterBeatsDragDelta +
    studioContext.getEffectiveSelection().endBeats +
    studioContext.contextAfterBeats;
  const contextWindowStartX = studioContext.beatsToCanvasX(
    contextWindowStartBeats
  );
  const contextWindowEndX = studioContext.beatsToCanvasX(contextWindowEndBeats);

  const contextWindowMiddleX = (contextWindowEndX + contextWindowStartX) / 2;
  return [
    {
      touchTarget: {
        bounds: {
          left: contextWindowStartX,
          right: contextWindowEndX,
          top: 0,
          bottom: RULER_HEIGHT,
        },
        hoverGroup: 'context-window',
      },
      renderTop: (ctx: CanvasRenderingContext2D, hovered: boolean) => {
        ctx.fillStyle = 'rgba(255,255,255,0.07)';
        ctx.beginPath();
        ctx.roundRect(
          contextWindowStartX,
          0,
          contextWindowEndX - contextWindowStartX,
          RULER_HEIGHT,
          4
        );
        ctx.closePath();
        ctx.fill();

        if (!hovered && !contextBeforeDragging && !contextAfterDragging) return;

        ctx.save();

        ctx.fillStyle = 'rgba(255,255,255,1)';
        ctx.strokeStyle = 'rgba(255,255,255,1)';

        ctx.font = '11px "Input Sans", monospace';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';
        ctx.fillStyle = 'rgba(255,255,255,1)';
        ctx.fillText(
          'CONTEXT WINDOW',
          (contextWindowEndX + contextWindowStartX) / 2,
          RULER_HEIGHT - 8
        );

        ctx.beginPath();
        ctx.roundRect(contextWindowStartX - 2, 2, 4, RULER_HEIGHT - 4, 2);
        ctx.roundRect(contextWindowEndX - 2, 2, 4, RULER_HEIGHT - 4, 2);
        ctx.closePath();
        ctx.fill();

        ctx.beginPath();
        ctx.moveTo(contextWindowStartX, RULER_HEIGHT - 4);
        ctx.lineTo(
          contextWindowStartX,
          studioContext.timelineController.getWrapperRect().height -
            SCROLLBAR_HEIGHT
        );

        ctx.moveTo(contextWindowEndX, RULER_HEIGHT - 4);
        ctx.lineTo(
          contextWindowEndX,
          studioContext.timelineController.getWrapperRect().height -
            SCROLLBAR_HEIGHT
        );
        ctx.closePath();
        ctx.stroke();

        ctx.restore();
      },
    },
    {
      touchTarget: {
        bounds: {
          left: contextWindowStartX - 4,
          right: contextWindowStartX + 4,
          top: 0,
          bottom: RULER_HEIGHT,
        },
        hoverGroup: 'context-window',
        hoverCursor: 'ew-resize',
        dragCursor: 'ew-resize',
        onDoubleClick: () => {
          studioContext.setContextWindowBeats(32);
        },
        onMouseDown: studioContext.handleClickDrag(({ downBeats }) => {
          const originalContextBeforeBeats = studioContext.contextBeforeBeats;
          const originalContextAfterBeats = studioContext.contextAfterBeats;
          contextBeforeDragging = true;
          return {
            onMouseMove: ({ moveBeats, moveEvent }) => {
              contextBeforeBeatsDragDelta = snapWithEvent(
                moveEvent,
                moveBeats - downBeats,
                studioContext.gridSizeRef.current
              );
              if (moveEvent.altKey) {
                contextAfterBeatsDragDelta = -contextBeforeBeatsDragDelta;
              } else {
                contextAfterBeatsDragDelta = 0;
              }
              studioContext.timelineController.frameCountRef.current++;
            },
            onMouseUp: ({ upEvent }) => {
              contextBeforeDragging = false;
              const delta = contextBeforeBeatsDragDelta;
              contextBeforeBeatsDragDelta = 0;
              contextAfterBeatsDragDelta = 0;
              studioContext.setContextWindowBeforeBeats(
                Math.max(0, originalContextBeforeBeats - delta)
              );
              if (upEvent.altKey) {
                studioContext.setContextWindowAfterBeats(
                  Math.max(0, originalContextAfterBeats - delta)
                );
              }
              studioContext.timelineController.frameCountRef.current++;
            },
          };
        }),
      },
    },
    {
      touchTarget: {
        bounds: {
          left: contextWindowEndX - 4,
          right: contextWindowEndX + 4,
          top: 0,
          bottom: RULER_HEIGHT,
        },
        hoverGroup: 'context-window',
        hoverCursor: 'ew-resize',
        dragCursor: 'ew-resize',
        onDoubleClick: () => {
          studioContext.setContextWindowBeats(32);
        },
        onMouseDown: studioContext.handleClickDrag(({ downBeats }) => {
          const originalContextBeforeBeats = studioContext.contextBeforeBeats;
          const originalContextAfterBeats = studioContext.contextAfterBeats;
          contextAfterDragging = true;
          return {
            onMouseMove: ({ moveBeats, moveEvent }) => {
              contextAfterBeatsDragDelta = snapWithEvent(
                moveEvent,
                moveBeats - downBeats,
                studioContext.gridSizeRef.current
              );
              if (moveEvent.altKey) {
                contextBeforeBeatsDragDelta = -contextAfterBeatsDragDelta;
              } else {
                contextBeforeBeatsDragDelta = 0;
              }
              studioContext.timelineController.frameCountRef.current++;
            },
            onMouseUp: ({ upEvent }) => {
              contextAfterDragging = false;
              const delta = contextAfterBeatsDragDelta;
              contextAfterBeatsDragDelta = 0;
              contextBeforeBeatsDragDelta = 0;
              studioContext.setContextWindowAfterBeats(
                Math.max(0, originalContextAfterBeats + delta)
              );
              if (upEvent.altKey) {
                studioContext.setContextWindowBeforeBeats(
                  Math.max(0, originalContextBeforeBeats + delta)
                );
              }
              studioContext.timelineController.frameCountRef.current++;
            },
          };
        }),
      },
    },
    {
      touchTarget: {
        bounds: {
          left: 0,
          right: 0,
          top: 0,
          bottom: 0,
        },
        hoverGroup: 'context-window',
        hoverCursor: 'pointer',
      },
      renderTop: (ctx: CanvasRenderingContext2D, hovered: boolean) => {
        if (!hovered) return;
        ctx.fillStyle = 'rgba(255,255,255,1)';
        ctx.beginPath();
        ctx.arc(
          contextWindowMiddleX + 70,
          RULER_HEIGHT - 15,
          5,
          0,
          2 * Math.PI
        );
        ctx.closePath();
        ctx.fill();

        ctx.save();
        ctx.font = '10px "PP Neue Montreal", sans-serif';
        ctx.fillStyle = 'rgba(10,10,12,1)';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText('?', contextWindowMiddleX + 70, RULER_HEIGHT - 14.5);
        ctx.restore();
      },
    },
    {
      touchTarget: {
        bounds: {
          left: contextWindowMiddleX + 70 - 10,
          right: contextWindowMiddleX + 70 + 10,
          top: RULER_HEIGHT - 15 - 10,
          bottom: RULER_HEIGHT - 15 + 10,
        },
        passthrough: true,
      },
      renderTop: (ctx: CanvasRenderingContext2D, hovered: boolean) => {
        if (!hovered) return;
        ctx.fillStyle = 'rgba(40,40,40,1)';
        ctx.beginPath();
        ctx.roundRect(contextWindowMiddleX - 105, RULER_HEIGHT - 1, 210, 40, 4);
        ctx.closePath();
        ctx.fill();
        ctx.font = '12px "PP Neue Montreal", sans-serif';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';
        ctx.fillStyle = 'rgba(255,255,255,1)';
        ctx.fillText(
          'Content before or after this region will',
          contextWindowMiddleX,
          RULER_HEIGHT + 18
        );
        ctx.fillText(
          'be ignored when creating new clips.',
          contextWindowMiddleX,
          RULER_HEIGHT + 34
        );
        ctx.closePath();
      },
    },
  ];
}
