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

import PlaybackProgress, {
  PlaybackProgressProps,
} from '@/components/mediaPlayback/PlaybackProgress';

import OmniplayerClipMetadata from './OmniplayerClipMetadata';
import OmniplayerClipVisualizer from './OmniplayerClipVisualizer';
import OmniplayerControls, {
  OmniplayerControlsProps,
} from './OmniplayerControls';

type KeysWithPrefix<T, Prefix extends string> = keyof {
  [K in keyof T as K extends string
    ? K extends `${Prefix}${string}`
      ? K
      : never
    : never]: T[K];
};

export type OmniplayerProps = {
  visualizerClassName?: string;
  metadataClassName?: string;
  controlsClassName?: string;
  clipId?: string;
} & Pick<
  OmniplayerControlsProps,
  | KeysWithPrefix<OmniplayerControlsProps, 'disabled'>
  | KeysWithPrefix<OmniplayerControlsProps, 'on'>
  | 'isPlaying'
  | 'volume'
  | 'muted'
  | 'shuffle'
  | 'repeat'
  | 'autoplay'
  | 'isLiked'
  | 'isDisliked'
> &
  Pick<
    PlaybackProgressProps,
    | 'currentTime'
    | 'duration'
    | 'estimatedDuration'
    | 'showTime'
    | 'showEstimatedDurationSpinner'
  >;

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

const Omniplayer: React.FC<Props> = (props) => {
  const {
    className,
    children,
    visualizerClassName,
    metadataClassName,
    controlsClassName,
    clipId,
    // OmniplayerControls
    isPlaying,
    volume,
    muted,
    repeat,
    autoplay,
    isLiked,
    isDisliked,
    disabledPlayPause,
    disabledPrevious,
    disabledNext,
    disabledRepeat,
    disabledAutoplay,
    onPlayPauseClick,
    onPreviousClick,
    onNextClick,
    onVolumeClick,
    onShuffleClick,
    onRepeatClick,
    onAutoplayClick,
    onQueueClick,
    onMoreActionsClick,
    onLikeClick,
    onDislikeClick,
    onCommentsClick,
    onShareClick,
    // Playtime
    currentTime,
    duration,
    estimatedDuration,
    showTime,
    showEstimatedDurationSpinner,
    ...restProps
  } = props;

  return (
    <div
      className={twMerge(
        'relative flex flex-row',
        'bg-background-primary text-foreground-primary',
        className
      )}
      {...restProps}
    >
      <div
        className={twMerge('relative aspect-9/16 w-80', visualizerClassName)}
      >
        <OmniplayerClipVisualizer
          className={twMerge('h-full w-full', visualizerClassName)}
          clipId={clipId}
          isPlaying={isPlaying}
        />
        <div
          className={twMerge(
            'absolute inset-x-0 bottom-0',
            'flex flex-col items-stretch justify-center gap-2 p-4 py-8',
            'bg-linear-to-t from-opacity-black-90',
            controlsClassName
          )}
        >
          <OmniplayerControls
            className='items-center justify-center bg-transparent'
            isPlaying={isPlaying}
            volume={volume}
            muted={muted}
            repeat={repeat}
            autoplay={autoplay}
            isLiked={isLiked}
            isDisliked={isDisliked}
            disabledPlayPause={disabledPlayPause}
            disabledPrevious={disabledPrevious}
            disabledNext={disabledNext}
            disabledRepeat={disabledRepeat}
            disabledAutoplay={disabledAutoplay}
            onPlayPauseClick={onPlayPauseClick}
            onPreviousClick={onPreviousClick}
            onNextClick={onNextClick}
            onVolumeClick={onVolumeClick}
            onShuffleClick={onShuffleClick}
            onRepeatClick={onRepeatClick}
            onAutoplayClick={onAutoplayClick}
            onQueueClick={onQueueClick}
            onMoreActionsClick={onMoreActionsClick}
            onLikeClick={onLikeClick}
            onDislikeClick={onDislikeClick}
            onCommentsClick={onCommentsClick}
            onShareClick={onShareClick}
          />
          <PlaybackProgress
            currentTime={currentTime}
            duration={duration}
            estimatedDuration={estimatedDuration}
            showTime={showTime}
            showEstimatedDurationSpinner={showEstimatedDurationSpinner}
          />
        </div>
      </div>
      <OmniplayerClipMetadata
        className={twMerge('relative min-w-0 flex-1 p-4', metadataClassName)}
        clipId={clipId}
      />
      {children}
    </div>
  );
};

export default Omniplayer;
