import { noop } from 'lodash-es';
import { observer } from 'mobx-react-lite';
import { useCallback } from 'react';

import stemIconMap from '@/app/(root)/stems/stemIconMap';
import useClip from '@/hooks/useClip';
import { useContextSelector } from '@/hooks/useContextSelector';
import {
  ArrowLeftIcon,
  DownloadIcon,
  MoreHorizontalIcon,
  StemsIcon,
} from '@/icons';
import { useApiClient } from '@/lib/apiClient';
import { downloadClipWav } from '@/utils/download';

import Button, { ButtonShape, ButtonVariant } from '../button/Button';
import { ContextMenuTrigger } from '../contextMenu/ContextMenu';
import StudioContext from '../studio/StudioContext';
import StudioSongRowWrapper from '../studio/StudioSongRowWrapper';
import autoArrangeStem from '../studio/actions/autoArrangeStem';
import useHasStudioContext from '../studio/useHasStudioContext';
import { NullableClipContextProvider } from './ClipContext';
import {
  ClipImage,
  ClipRowGroup,
  ClipRowHeightMicro,
  MicroClipRowWrapper,
} from './ClipElements';
import { MoreMenuContents } from './ClipMenus';
import { AutoClipPlaybackProvider } from './useClipPlayback';
import virtualizeClipRow from './virtualizeClipRow';

export const UnvirtualizedStemClipRow = observer(
  ({
    clipId,
    arrangementMatchClipId,
    parentDownbeats,
    parentDurationSeconds,
  }: {
    clipId: string;
    arrangementMatchClipId?: string;
    parentDownbeats?: [number, number][];
    parentDurationSeconds?: number;
  }) => {
    const { clip } = useClip(clipId);
    const apiClient = useApiClient();
    const hasStudioContext = useHasStudioContext();
    const setState = useContextSelector(
      StudioContext,
      (ctx) => ctx?.setState || noop
    );

    const stemGroup = clip?.metadata?.stem_type_group_name;
    const IconComponent = stemGroup
      ? (stemIconMap[stemGroup as keyof typeof stemIconMap] ?? StemsIcon)
      : StemsIcon;

    const insertStem = useCallback(() => {
      if (clip && parentDownbeats && parentDurationSeconds) {
        setState(
          autoArrangeStem(
            clip,
            parentDownbeats,
            parentDurationSeconds,
            arrangementMatchClipId
          )
        );
      }
    }, [
      clip,
      setState,
      arrangementMatchClipId,
      parentDownbeats,
      parentDurationSeconds,
    ]);

    return (
      <AutoClipPlaybackProvider clip={clip}>
        <NullableClipContextProvider clip={clip}>
          <StudioSongRowWrapper
            clipId={clipId}
            bypassIntersectionCheck
            childrenHeight={ClipRowHeightMicro}
          >
            <MicroClipRowWrapper className='clip-row'>
              <ClipRowGroup tight>
                <ClipImage small />
                <IconComponent className='h-4 w-4' />
                <span
                  className='max-w-20 truncate'
                  title={
                    clip?.metadata.stem_type_group_name ||
                    clip?.metadata.control_tags?.replace(/^add\s+/i, '') ||
                    ''
                  } // remove "add" prefix from control tags
                >
                  {clip?.metadata.stem_type_group_name?.replace(
                    'Backing_Vocals',
                    'B Vocals'
                  ) || clip?.metadata.control_tags?.replace(/^add\s+/i, '')}
                </span>
              </ClipRowGroup>
              <ClipRowGroup className='shrink-0' tight>
                {hasStudioContext ? (
                  <Button
                    className='hover-fade-in -mr-2 p-2'
                    shape={ButtonShape.Pill}
                    variant={ButtonVariant.Tertiary}
                    icon={<ArrowLeftIcon className='h-4 w-4' />}
                    onClick={() => {
                      insertStem();
                    }}
                  />
                ) : (
                  <Button
                    className='hover-fade-in -mr-2 p-2'
                    shape={ButtonShape.Pill}
                    variant={ButtonVariant.Tertiary}
                    icon={<DownloadIcon className='h-4 w-4' />}
                    onClick={() => {
                      if (clip) downloadClipWav(apiClient, clip.id);
                    }}
                  />
                )}
                <ContextMenuTrigger
                  ButtonComponent={(props) => (
                    <Button
                      className='hover-fade-in p-2'
                      shape={ButtonShape.Pill}
                      variant={ButtonVariant.Tertiary}
                      icon={<MoreHorizontalIcon className='h-4 w-4' />}
                      {...props}
                    />
                  )}
                  ContentsComponent={MoreMenuContents}
                />
              </ClipRowGroup>
            </MicroClipRowWrapper>
          </StudioSongRowWrapper>
        </NullableClipContextProvider>
      </AutoClipPlaybackProvider>
    );
  }
);

export const StemClipRow = virtualizeClipRow(
  UnvirtualizedStemClipRow,
  MicroClipRowWrapper
);
