import { useState, useEffect } from 'react';
import { MediaSet } from './generated/media_set';
import { Frames, VideoPosition } from './App';
import { WaveformCanvas } from './WaveformCanvas';
import {
  HudCanvas,
  EmptySelectionAction,
  SelectionChangeEvent,
} from './HudCanvas';
import { SelectionMode } from './HudCanvasState';
import { Observable } from 'rxjs';

export interface Selection {
  start: number;
  end: number;
}

interface Props {
  peaks: Observable<number[]>;
  mediaSet: MediaSet;
  position: VideoPosition;
  viewport: Frames;
  onSelectionChange: (selectionState: SelectionChangeEvent) => void;
}

export const CanvasLogicalWidth = 2_000;
export const CanvasLogicalHeight = 500;

export const Overview: React.FC<Props> = ({
  peaks,
  mediaSet,
  position,
  viewport,
  onSelectionChange,
}: Props) => {
  const [selectedPixels, setSelectedPixels] = useState({ start: 0, end: 0 });
  const [positionPixels, setPositionPixels] = useState(0);

  // side effects

  // convert viewport from frames to canvas pixels.
  // TODO: consider an adapter component to handle this.
  useEffect(() => {
    setSelectedPixels({
      start: Math.round(
        (viewport.start / mediaSet.audioFrames) * CanvasLogicalWidth
      ),
      end: Math.round(
        (viewport.end / mediaSet.audioFrames) * CanvasLogicalWidth
      ),
    });
  }, [viewport, mediaSet]);

  // convert position from frames to canvas pixels:
  // TODO: consider an adapter component to handle this.
  useEffect(() => {
    const ratio =
      position.currentTime / (mediaSet.audioFrames / mediaSet.audioSampleRate);
    setPositionPixels(Math.round(ratio * CanvasLogicalWidth));
    frames;
  }, [mediaSet, position]);

  // handlers

  // convert selection change from canvas pixels to frames, and trigger callback.
  const handleSelectionChange = (selectionState: SelectionChangeEvent) => {
    const {
      mode,
      prevMode,
      selection: { start, end },
    } = selectionState;

    if (mode != SelectionMode.Normal || prevMode == SelectionMode.Normal) {
      return;
    }

    onSelectionChange({
      ...selectionState,
      selection: {
        start: Math.round((start / CanvasLogicalWidth) * mediaSet.audioFrames),
        end: Math.round((end / CanvasLogicalWidth) * mediaSet.audioFrames),
      },
    });
  };

  // render component

  const hudStyles = {
    borderLineWidth: 4,
    borderStrokeStyle: 'red',
    positionLineWidth: 4,
    positionStrokeStyle: 'red',
    hoverPositionStrokeStyle: 'transparent',
  };

  return (
    <>
      <div className={`relative grow-0 h-16`}>
        <WaveformCanvas
          peaks={peaks}
          channels={mediaSet.audioChannels}
          width={CanvasLogicalWidth}
          height={CanvasLogicalHeight}
          strokeStyle="black"
          fillStyle="#003300"
          alpha={1}
        ></WaveformCanvas>
        <HudCanvas
          width={CanvasLogicalWidth}
          height={CanvasLogicalHeight}
          emptySelectionAction={EmptySelectionAction.SelectPrevious}
          styles={hudStyles}
          position={positionPixels}
          selection={selectedPixels}
          onSelectionChange={handleSelectionChange}
        />
      </div>
    </>
  );
};
