import { useMemo } from 'react';
import { twMerge } from 'tailwind-merge';

import { useHooksLyrics } from '@/hooks/useAlignedLyrics';

import LyricsRenderer, {
  LyricsHighlightMode,
  LyricsRendererProps,
} from '../omniplayer/LyricsRenderer';
import { HookLyricDisplay } from './constants';

export type HooksLyricOverlayProps = Omit<
  LyricsRendererProps,
  'alignedLyrics'
> & {
  hookId?: string;
  clipId?: string;
  clipStartTime?: number;
  clipEndTime?: number;
  isPlaying?: boolean;
  lyricDisplayStyle?: HookLyricDisplay | `${HookLyricDisplay}`;
};

export type Props = Omit<
  React.HTMLAttributes<HTMLDivElement>,
  keyof HooksLyricOverlayProps
> &
  HooksLyricOverlayProps;

const HooksLyricOverlay: React.FC<Props> = (props) => {
  const {
    className: explicitClassName,
    lineClassName: explicitLineClassName,
    wordClassName: explicitWordClassName,
    hookId,
    clipId,
    clipStartTime = 0,
    clipEndTime = Infinity,
    currentTime: hookCurrentTime,
    isPlaying, // passed in by HooksPlayer but not used
    lyricDisplayStyle = HookLyricDisplay.BottomLeft,
    ...restProps
  } = props;

  const clipCurrentTime =
    hookCurrentTime == null ? undefined : hookCurrentTime + clipStartTime;

  const { alignedLyrics: clipAlignedLyrics } = useHooksLyrics(hookId || '', {
    enabled: !!hookId,
  });

  const lyricDisplayProps = useMemo<Partial<LyricsRendererProps>>(() => {
    switch (lyricDisplayStyle) {
      case HookLyricDisplay.CenteredLine:
        return {
          className: twMerge(
            'w-2/3 pb-20',
            'text-center font-sans font-extrabold',
            'text-2xl [text-shadow:1px_1px_0_rgba(0,0,0,0.6)]',
            'md:text-4xl md:[text-shadow:2px_2px_0_rgba(0,0,0,0.6)]',
            explicitClassName
          ),
          lineClassName: twMerge(
            'hidden data-highlight:block',
            'animate-fade-in',
            explicitLineClassName
          ),
          wordClassName: twMerge(
            'text-dumbo-800',
            'data-highlight:text-white',
            'data-highlight:duration-100',
            'transition-colors',
            explicitWordClassName
          ),
          highlightMode: LyricsHighlightMode.Line,
        };
      case HookLyricDisplay.CenteredWord:
        return {
          className: twMerge(
            'w-2/3 pb-20',
            'text-center font-sans font-extrabold',
            'text-2xl [text-shadow:1px_1px_0_rgba(0,0,0,0.6)]',
            'md:text-4xl md:[text-shadow:2px_2px_0_rgba(0,0,0,0.6)]',
            explicitClassName
          ),
          lineClassName: twMerge(
            'hidden data-highlight:block',
            'animate-fade-in',
            explicitLineClassName
          ),
          wordClassName: twMerge(
            'hidden data-highlight:block',
            'text-white data-highlight:text-white',
            explicitWordClassName
          ),
          highlightMode: LyricsHighlightMode.Word,
          groupLines: false,
        };
      case HookLyricDisplay.BottomLeft:
      default:
        return {
          className: twMerge('font-sans text-xl font-bold', explicitClassName),
          lineClassName: twMerge(
            'hidden data-highlight:block',
            'animate-fade-in',
            explicitLineClassName
          ),
          wordClassName: twMerge(
            'text-foreground-tertiary-glass',
            'data-highlight:text-foreground-primary-glass',
            'data-highlight:duration-100',
            'transition-colors',
            explicitWordClassName
          ),
          highlightMode: LyricsHighlightMode.Group,
          groupLines: true,
          maxGroupDuration: Infinity,
          maxLinesPerGroup: 2,
        };
    }
  }, [
    lyricDisplayStyle,
    explicitClassName,
    explicitLineClassName,
    explicitWordClassName,
  ]);

  // Filter out lines that aren't part of the hook
  const alignedLyrics = useMemo(
    () =>
      clipAlignedLyrics &&
      (clipStartTime || clipEndTime
        ? clipAlignedLyrics.filter(
            (line) =>
              // Starts within the snippet
              (line.startS >= clipStartTime && line.startS <= clipEndTime) ||
              // Ends within the snippet
              (line.endS >= clipStartTime && line.endS <= clipEndTime) ||
              // Spans the snippet
              (line.startS <= clipStartTime && line.endS >= clipStartTime)
          )
        : clipAlignedLyrics),
    [clipAlignedLyrics, clipStartTime, clipEndTime]
  );

  if (!alignedLyrics?.length) {
    return null;
  }

  return (
    <LyricsRenderer
      alignedLyrics={alignedLyrics}
      currentTime={clipCurrentTime}
      // Highlight a little early to compensate for the fade-in
      highlightLineOffsetStart={-0.1}
      highlightLineOffsetEnd={-0.1}
      highlightWordOffsetStart={-0.1}
      highlightWordOffsetEnd={-0.1}
      {...lyricDisplayProps}
      {...restProps}
    />
  );
};

export const HooksLyricsOverlayCenter: React.FC<Props> = (props) => {
  const {
    className: explicitClassName,
    lineClassName: explicitLineClassName,
    wordClassName: explicitWordClassName,
    ...restProps
  } = props;
  return (
    <div>
      <div
        className={twMerge(
          'pointer-events-none m-auto flex aspect-9/16 h-full max-w-full flex-col items-center justify-center',
          explicitClassName
        )}
      >
        <HooksLyricOverlay {...restProps} />
      </div>
    </div>
  );
};

export default HooksLyricOverlay;
