import * as React from 'react';
import {WaveSurferOptions} from 'wavesurfer.js';
import clsx from 'clsx';

type WaveSurferCanvasDerivedComponent = HTMLAudioElement;

export interface WaveSurferCanvasProps
  extends React.HTMLProps<WaveSurferCanvasDerivedComponent>,
    Omit<WaveSurferOptions, 'height' | 'media' | 'container' | 'fillParent' | 'url' | 'autoplay' | 'renderFunction'> {}

export const WaveSurferCanvas = React.forwardRef<WaveSurferCanvasDerivedComponent, WaveSurferCanvasProps>(({
  className,
  children,
  controls,
  waveColor,
  progressColor,
  cursorColor,
  cursorWidth,
  barWidth,
  barGap,
  barRadius,
  barHeight,
  barAlign,
  minPxPerSec,
  peaks,
  duration,
  autoPlay,
  interact,
  hideScrollbar,
  audioRate,
  autoScroll,
  autoCenter,
  sampleRate,
  splitChannels,
  normalize,
  plugins,
  ...etcProps
}, forwardedRef) => {
  const [isPlaying, setIsPlaying] = React.useState(false);
  const defaultRef = React.useRef<HTMLAudioElement>(null);
  const ref = forwardedRef ?? defaultRef;
  const containerRef = React.useRef<HTMLDivElement>(null);
  const waveSurferRef = React.useRef<any>(null);

  const handleAction: React.FormEventHandler<HTMLFormElement> = (e) => {
    e.preventDefault();
    const formData = new FormData(e.currentTarget, (e.nativeEvent as unknown as { submitter: HTMLElement }).submitter);
    const action = formData.get('action');
    switch (action) {
    case 'togglePlayback':
      setIsPlaying((prev) => !prev);
      break;
    default:
      break;
    }
  };

  React.useEffect(() => {
    const { current: container } = containerRef;
    const media = typeof ref === 'object' ? ref?.current : null;
    const { current: waveSurferCurrent } = waveSurferRef;

    const load = async (ref: React.Ref<HTMLAudioElement>) => {
      if (!(typeof ref === 'object' && ref?.current)) {
        return;
      }

      if (!(typeof containerRef === 'object' && containerRef?.current)) {
        return;
      }
      const { default: WaveSurfer } = await import('wavesurfer.js');
      //const a = await import('wavesurfer.js/dist/plugins/spectrogram');
      const waveSurferInstance = WaveSurfer.create({
        container: containerRef.current,
        height: containerRef.current.clientHeight,
        fillParent: true,
        autoplay: autoPlay,
        waveColor,
        progressColor,
        cursorColor,
        barWidth,
        barGap,
        barRadius,
        barHeight,
        barAlign,
        minPxPerSec,
        peaks,
        duration,
        interact,
        hideScrollbar,
        audioRate,
        autoScroll,
        autoCenter,
        sampleRate,
        splitChannels,
        normalize,
        plugins,
        cursorWidth,
        media: media ?? undefined,
      });
      waveSurferInstance.on('ready', () => {
        if (!container) {
          return;
        }
        while (container.children.length > 1) {
          container.removeChild(container.children[0]);
        }
      });
      await waveSurferInstance.load(ref.current.currentSrc);
      waveSurferInstance.setTime(ref.current.currentTime);
      waveSurferRef.current = waveSurferInstance;
    };
    void load(ref);
    return () => {
      if (waveSurferCurrent) {
        (waveSurferCurrent as unknown as Record<string, Function>).destroy();
      }
      if (container) {
        container.innerHTML = '';
      }
    };
  }, [
    ref,
    autoPlay,
    waveColor,
    progressColor,
    cursorColor,
    barWidth,
    barGap,
    barRadius,
    barHeight,
    barAlign,
    minPxPerSec,
    peaks,
    duration,
    interact,
    hideScrollbar,
    audioRate,
    autoScroll,
    autoCenter,
    sampleRate,
    splitChannels,
    normalize,
    plugins,
    cursorWidth,
  ]);

  return (
    <div
      className={clsx(
        'relative flex flex-col',
        className,
      )}
    >
      <div
        className="flex-auto relative"
      >
        <div className="absolute top-0 left-0 w-full h-full"
          ref={containerRef}
        />
      </div>
      {controls && (
        <form
          onSubmit={handleAction}
        >
          <button
            type="submit"
            name="action"
            value="togglePlayback"
          >
            {isPlaying ? '⏸' : '▶'}
          </button>
        </form>
      )}
    </div>
  );
});

WaveSurferCanvas.displayName = 'WavesurferCanvas';
