import { useCallback } from 'react';

import { useContextSelector } from '@/hooks/useContextSelector';
import { CaretLeftIcon, CaretRightIcon } from '@/icons';

import Button, { ButtonShape, ButtonVariant } from '../../button/Button';
import {
  ContextMenuItem,
  ContextMenuTrigger,
} from '../../contextMenu/ContextMenu';
import StudioContext from '../../studio/StudioContext';
import updateTrack from '../../studio/actions/updateTrack';
import { StudioTrack, TrackEQ } from '../../studio/types';
import { useEQState } from './EQStateContext';
import { EQ_PRESETS, getCurrentPresetName } from './eqPresets';

const PRESET_NAMES = Object.keys(EQ_PRESETS);

export default function PresetSelector({ track }: { track: StudioTrack }) {
  const setState = useContextSelector(StudioContext, (ctx) => ctx?.setState);
  const eqState = useEQState();

  const applyPreset = useCallback(
    (preset: TrackEQ) => {
      if (!setState) return;

      setState(
        updateTrack(track.id, (t) => ({
          ...t,
          eq: preset,
        }))
      );

      // Select first enabled band if current selection becomes disabled
      eqState.selectFirstEnabledBandIfNeeded(preset);
    },
    [track.id, setState, eqState]
  );

  const currentPresetName = getCurrentPresetName(track.eq);
  const isCustom = currentPresetName === null;

  const navigatePreset = useCallback(
    (direction: 'prev' | 'next') => {
      const currentIndex = currentPresetName
        ? PRESET_NAMES.indexOf(currentPresetName)
        : -1;

      let newIndex: number;
      if (currentIndex === -1) {
        // If custom, go to first or last preset
        newIndex = direction === 'next' ? 0 : PRESET_NAMES.length - 1;
      } else {
        newIndex =
          direction === 'next'
            ? (currentIndex + 1) % PRESET_NAMES.length
            : (currentIndex - 1 + PRESET_NAMES.length) % PRESET_NAMES.length;
      }

      const newPresetName = PRESET_NAMES[newIndex];
      const newPreset = EQ_PRESETS[newPresetName];
      applyPreset(newPreset);
    },
    [currentPresetName, applyPreset]
  );

  return (
    <div className='mt-2 flex flex-col gap-2'>
      <div className='text-md'>Preset</div>
      <div className='flex flex-row items-center justify-between gap-2'>
        <Button
          variant={ButtonVariant.LightGlass}
          shape={ButtonShape.Pill}
          icon={<CaretLeftIcon className='h-5 w-5' />}
          onClick={() => navigatePreset('prev')}
        />
        <ContextMenuTrigger
          className='w-full'
          placement='bottom-middle'
          ButtonComponent={(props) => (
            <Button
              {...props}
              variant={ButtonVariant.Secondary}
              shape={ButtonShape.Pill}
              className='w-full flex-1'
            >
              <span className={isCustom ? 'italic opacity-50' : ''}>
                {isCustom ? '[Custom]' : currentPresetName}
              </span>
            </Button>
          )}
          ContentsComponent={() => (
            <>
              {(Object.entries(EQ_PRESETS) as [string, TrackEQ][]).map(
                ([name, preset]) => {
                  const isActive = currentPresetName === name;
                  return (
                    <ContextMenuItem
                      key={name}
                      className={
                        isActive ? 'bg-background-glass-thick py-1.5' : 'py-1.5'
                      }
                      onClick={() => applyPreset(preset)}
                    >
                      {name}
                    </ContextMenuItem>
                  );
                }
              )}
            </>
          )}
        />
        <Button
          variant={ButtonVariant.LightGlass}
          shape={ButtonShape.Pill}
          icon={<CaretRightIcon className='h-5 w-5' />}
          onClick={() => navigatePreset('next')}
        />
      </div>
    </div>
  );
}
