import { useEffect, useState } from 'react';
import { Center, Group } from '@mantine/core';
import { AnimatePresence, motion } from 'framer-motion';
import { ErrorBoundary } from 'react-error-boundary';
import { RiInformationFill } from 'react-icons/ri';
import styled from 'styled-components';
import { useSongLyrics } from './queries/lyric-query';
import { SynchronizedLyrics } from './synchronized-lyrics';
import { ScrollArea, Spinner, TextTitle } from '/@/renderer/components';
import { ErrorFallback } from '/@/renderer/features/action-required';
import { UnsynchronizedLyrics } from '/@/renderer/features/lyrics/unsynchronized-lyrics';
import { getServerById, useCurrentSong } from '/@/renderer/store';
import { FullLyricsMetadata, SynchronizedLyricMetadata } from '/@/renderer/api/types';
import { LyricsActions } from '/@/renderer/features/lyrics/lyrics-actions';

const ActionsContainer = styled.div`
  position: absolute;
  bottom: 4rem;
  left: 0;
  z-index: 50;
  display: flex;
  gap: 0.5rem;
  align-items: center;
  justify-content: center;
  width: 100%;
  opacity: 0;
  transition: opacity 0.2s ease-in-out;

  &:hover {
    opacity: 1 !important;
  }
`;

const LyricsContainer = styled.div`
  position: relative;
  width: 100%;
  height: 100%;

  &:hover {
    ${ActionsContainer} {
      opacity: 0.5;
    }
  }
`;

const ScrollContainer = styled(motion(ScrollArea))`
  position: relative;
  z-index: 1;
  text-align: center;
  transform: translateY(-2rem);

  mask-image: linear-gradient(
    180deg,
    transparent 5%,
    rgba(0, 0, 0, 100%) 20%,
    rgba(0, 0, 0, 100%) 85%,
    transparent 95%
  );

  &.mantine-ScrollArea-root {
    height: 100%;
  }

  & .mantine-ScrollArea-viewport {
    height: 100% !important;
  }

  & .mantine-ScrollArea-viewport > div {
    height: 100%;
  }
`;

function isSynchronized(data: FullLyricsMetadata): data is SynchronizedLyricMetadata {
  // Type magic. The only difference between Synchronized and Unsynchhronized is
  // the datatype of lyrics. This makes Typescript happier later...
  return Array.isArray(data.lyrics);
}

export const Lyrics = () => {
  const currentSong = useCurrentSong();
  const currentServer = getServerById(currentSong?.serverId);

  const [clear, setClear] = useState(false);

  const { data, isInitialLoading } = useSongLyrics(
    {
      query: { songId: currentSong?.id || '' },
      serverId: currentServer?.id,
    },
    currentSong,
  );

  useEffect(() => {
    // We want to reset the clear flag whenever a song changes
    setClear(false);
  }, [currentSong]);

  return (
    <ErrorBoundary FallbackComponent={ErrorFallback}>
      {isInitialLoading ? (
        <Spinner
          container
          size={25}
        />
      ) : (
        <AnimatePresence mode="sync">
          <LyricsContainer>
            {!data?.lyrics || clear ? (
              <Center>
                <Group>
                  <RiInformationFill size="2rem" />
                  <TextTitle
                    order={3}
                    weight={700}
                  >
                    No lyrics found
                  </TextTitle>
                </Group>
              </Center>
            ) : (
              <ScrollContainer
                animate={{ opacity: 1 }}
                initial={{ opacity: 0 }}
                scrollHideDelay={0}
                transition={{ duration: 0.5 }}
              >
                {isSynchronized(data) ? (
                  <SynchronizedLyrics
                    {...data}
                    onRemoveLyric={() => setClear(true)}
                  />
                ) : (
                  <UnsynchronizedLyrics
                    {...data}
                    onRemoveLyric={() => setClear(true)}
                  />
                )}
              </ScrollContainer>
            )}

            <ActionsContainer>
              <LyricsActions />
            </ActionsContainer>
          </LyricsContainer>
        </AnimatePresence>
      )}
    </ErrorBoundary>
  );
};
