import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import {
  Dispatch,
  SetStateAction,
  useCallback,
  useEffect,
  useRef,
  useState,
} from 'react';

import Button, { ButtonShape, ButtonVariant } from '@/components/button/Button';
import StudioLyricsDisplayV2 from '@/components/studio/StudioLyricsDisplayV2';
import {
  setSelectionEndSeconds as setSelectionEndSecondsAction,
  setSelectionStartSeconds as setSelectionStartSecondsAction,
} from '@/components/studio/actions/setSelectionSeconds';
import {
  getSelectionEndSeconds,
  getSelectionStartSeconds,
} from '@/components/studio/selectors';
import { useContextSelector } from '@/hooks/useContextSelector';
import { CollapseContentIcon, ExpandContentIcon } from '@/icons';

import { CreateModes } from '../../v2/types';
import CreateAudioDisplay from './CreateAudioDisplay';
import CreateCard from './CreateCard';
import StudioCreateContext from './StudioCreateContext';
import { CollapsibleCardTitle } from './common';
import { CreateTheme, bigButton, bigSpace } from './themes';
import useResizer, {
  RESIZABLE_CONTAINER_CLASS_NAME,
  ResizerHandle,
} from './useResizer';

const ContentWrapper = styled.div`
  padding: 0 ${bigSpace}px ${bigSpace}px ${bigSpace}px;
  display: flex;
  flex-direction: column;
  gap: ${bigSpace}px;
  position: relative;
  height: 100%;
`;

const Footer = styled.div`
  position: absolute;
  bottom: ${bigSpace}px;
  right: ${bigSpace}px;
`;

const EditInput = styled.input`
  width: ${(props) => 48 + 2 * bigSpace(props)}px;
  height: ${bigButton}px;
  background-color: transparent;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: ${bigButton}px;
  padding: 0 ${bigSpace}px;
  display: flex;
  align-items: center;
  text-align: center;
  justify-content: center;
`;

const LyricsWrapper = styled.div`
  width: 100%;
  overflow-y: auto;
`;

const LyricsDisplayCard = ({
  editSelectionLyricsDisplayHeight,
  setEditSelectionLyricsDisplayHeight,
  lockScroll,
}: {
  editSelectionLyricsDisplayHeight: number;
  setEditSelectionLyricsDisplayHeight: Dispatch<SetStateAction<number>>;
  lockScroll: boolean;
}) => {
  const [fixAlignment, setFixAlignment] = useState(false);
  const lyricsWrapperRef = useRef<HTMLDivElement>(null);
  const [popout, setPopout] = useState(false);

  const receiveResizerRef = useResizer({
    height: editSelectionLyricsDisplayHeight,
    setHeight: setEditSelectionLyricsDisplayHeight,
    minHeight: 120,
    fullHeight: popout,
    resizeTargetRef: lyricsWrapperRef,
  });

  const handleFixAlignment = useCallback(() => {
    setFixAlignment(!fixAlignment);
  }, [fixAlignment]);

  const theme = useTheme() as CreateTheme;

  return (
    <CreateCard
      nested
      popout={popout}
      popoutRounded
      title={<CollapsibleCardTitle title='Lyrics' />}
      headerContent={
        <Button
          shape={ButtonShape.Pill}
          variant={ButtonVariant.LightGlass}
          onClick={handleFixAlignment}
          aria-label={
            fixAlignment ? 'Discard alignment changes' : 'Fix lyrics alignment'
          }
          style={{
            height: theme.dimensions.bigButton,
            padding: `0 ${theme.dimensions.mediumSpace * 2}px`,
          }}
        >
          {fixAlignment ? 'Discard Changes' : 'Fix Alignment'}
        </Button>
      }
    >
      <ContentWrapper>
        <LyricsWrapper ref={lyricsWrapperRef}>
          <StudioLyricsDisplayV2
            fixAlignment={fixAlignment}
            lockScroll={lockScroll}
          />
        </LyricsWrapper>
        <Footer>
          <Button
            shape={ButtonShape.Pill}
            variant={popout ? ButtonVariant.Primary : ButtonVariant.LightGlass}
            icon={
              popout ? (
                <CollapseContentIcon className='h-5 w-5' />
              ) : (
                <ExpandContentIcon className='h-5 w-5' />
              )
            }
            className='p-2'
            aria-label={
              popout ? 'Collapse lyrics editor' : 'Expand lyrics editor'
            }
            onClick={() => setPopout(!popout)}
          />
        </Footer>
      </ContentWrapper>
      {!popout && <ResizerHandle ref={receiveResizerRef} />}
    </CreateCard>
  );
};

const EditCard = ({
  expanded,
  setExpanded,
  editSelectionLyricsDisplayHeight,
  setEditSelectionLyricsDisplayHeight,
  selectionStartSeconds,
  selectionEndSeconds,
  setSelectionStartSeconds,
  setSelectionEndSeconds,
  sampleAudio,
  frameCountRef,
}: {
  expanded: boolean;
  setExpanded: Dispatch<SetStateAction<boolean>>;
  editSelectionLyricsDisplayHeight: number;
  setEditSelectionLyricsDisplayHeight: Dispatch<SetStateAction<number>>;
  selectionStartSeconds: number;
  selectionEndSeconds: number;
  setSelectionStartSeconds: (seconds: number) => void;
  setSelectionEndSeconds: (seconds: number) => void;
  sampleAudio: (progress: number) => number;
  frameCountRef?: React.RefObject<number>;
}) => {
  const [progress, setProgress] = useState(0);

  const [startSeconds, setStartSeconds] = useState(
    String(selectionStartSeconds)
  );
  const [endSeconds, setEndSeconds] = useState(String(selectionEndSeconds));
  const submitStartSeconds = useCallback(() => {
    const intended = Number(startSeconds);
    if (isNaN(intended)) {
      setStartSeconds(String(selectionStartSeconds));
    } else {
      setSelectionStartSeconds(intended);
    }
  }, [startSeconds, selectionStartSeconds, setSelectionStartSeconds]);

  const submitEndSeconds = useCallback(() => {
    const intended = Number(endSeconds);
    if (isNaN(intended)) {
      setEndSeconds(String(selectionEndSeconds));
    } else {
      setSelectionEndSeconds(intended);
    }
  }, [endSeconds, selectionEndSeconds, setSelectionEndSeconds]);

  useEffect(() => {
    setStartSeconds(selectionStartSeconds.toFixed(2));
    setEndSeconds(selectionEndSeconds.toFixed(2));
  }, [selectionStartSeconds, selectionEndSeconds]);

  return (
    <CreateCard
      collapsible
      expanded={expanded}
      setExpanded={setExpanded}
      title={<CollapsibleCardTitle title='Selection' />}
      className={RESIZABLE_CONTAINER_CLASS_NAME}
      headerContentHidden={false}
      headerContent={
        <>
          <EditInput
            value={startSeconds}
            onChange={(e) => setStartSeconds(e.target.value)}
            onBlur={submitStartSeconds}
            onKeyDown={(e) => {
              if (e.key === 'Enter') {
                submitStartSeconds();
              } else if (e.key === ' ') {
                e.preventDefault();
              }
            }}
          />
          &ndash;
          <EditInput
            value={endSeconds}
            onChange={(e) => setEndSeconds(e.target.value)}
            onBlur={submitEndSeconds}
            onKeyDown={(e) => {
              if (e.key === 'Enter') {
                submitEndSeconds();
              } else if (e.key === ' ') {
                e.preventDefault();
              }
            }}
          />
        </>
      }
    >
      <ContentWrapper>
        <CreateAudioDisplay
          sampleAudio={sampleAudio}
          getCurrentProgress={() => progress}
          setCurrentProgress={setProgress}
          frameCountRef={frameCountRef}
        />
        <LyricsDisplayCard
          editSelectionLyricsDisplayHeight={editSelectionLyricsDisplayHeight}
          setEditSelectionLyricsDisplayHeight={
            setEditSelectionLyricsDisplayHeight
          }
          lockScroll={!expanded}
        />
      </ContentWrapper>
    </CreateCard>
  );
};

export const StudioEditCard = () => {
  const selectionStartSeconds = useContextSelector(
    StudioCreateContext,
    ({ studio }) => getSelectionStartSeconds(studio.state)
  );
  const selectionEndSeconds = useContextSelector(
    StudioCreateContext,
    ({ studio }) => getSelectionEndSeconds(studio.state)
  );
  const setState = useContextSelector(
    StudioCreateContext,
    ({ studio }) => studio.setState
  );
  const [expanded, setExpanded] = useContextSelector(
    StudioCreateContext,
    ({ create }) =>
      create.selectState<boolean>([
        CreateModes.STUDIO_EDIT,
        'editSelectionExpanded',
      ])
  );
  const [
    editSelectionLyricsDisplayHeight,
    setEditSelectionLyricsDisplayHeight,
  ] = useContextSelector(StudioCreateContext, ({ create }) =>
    create.selectState<number>([
      CreateModes.STUDIO_EDIT,
      'editSelectionLyricsDisplayHeight',
    ])
  );

  const setSelectionStartSeconds = useCallback(
    (s: number) => setState(setSelectionStartSecondsAction(s)),
    [setState]
  );

  const setSelectionEndSeconds = useCallback(
    (s: number) => setState(setSelectionEndSecondsAction(s)),
    [setState]
  );

  const sampleAudio = useCallback(() => 0, []);

  return (
    <EditCard
      expanded={expanded}
      setExpanded={setExpanded}
      editSelectionLyricsDisplayHeight={editSelectionLyricsDisplayHeight}
      setEditSelectionLyricsDisplayHeight={setEditSelectionLyricsDisplayHeight}
      selectionStartSeconds={selectionStartSeconds}
      selectionEndSeconds={selectionEndSeconds}
      setSelectionStartSeconds={setSelectionStartSeconds}
      setSelectionEndSeconds={setSelectionEndSeconds}
      sampleAudio={sampleAudio}
    />
  );
};

export default EditCard;
