import { SyntheticEvent, useEffect, useRef, useState } from 'react';

import {
  Box,
  Button,
  Flex,
  IconButton,
  Slider,
  SliderFilledTrack,
  SliderThumb,
  SliderTrack,
  Text,
  position,
} from '@chakra-ui/react';
import {
  MdCheck,
  MdFastForward,
  MdFastRewind,
  MdGraphicEq,
  MdLooksOne,
  MdNavigateBefore,
  MdNavigateNext,
  MdOutlinePlayArrow,
  MdPause,
  MdPlayArrow,
  MdRepeat,
  MdRepeatOne,
  MdStop,
  MdTrendingFlat,
} from 'react-icons/md';

import { useActivePlaylistService } from '@/service/ActivePlaylist';
import { useSpecificAlbum } from '@/service/Album';
import { useSpecificArtists } from '@/service/Artist';
import { useSpecificGender } from '@/service/Gender';
import { useSpecificTrack } from '@/service/Track';
import { DataUrlAccess } from '@/utils/data-url-access';
import { useThemeMode } from '@/utils/theme-tools';
import { isNullOrUndefined } from '@/utils/validator';

export enum PlayMode {
  PLAY_ONE,
  PLAY_ALL,
  PLAY_ONE_LOOP,
  PLAY_ALL_LOOP,
}

const playModeIcon = {
  [PlayMode.PLAY_ONE]: <MdLooksOne size="30px" />,
  [PlayMode.PLAY_ALL]: <MdTrendingFlat size="30px" />,
  [PlayMode.PLAY_ONE_LOOP]: <MdRepeatOne size="30px" />,
  [PlayMode.PLAY_ALL_LOOP]: <MdRepeat size="30px" />,
};

export type AudioPlayerProps = {};

const formatTime = (time) => {
  if (time && !isNaN(time)) {
    const minutes = Math.floor(time / 60);
    const formatMinutes = minutes < 10 ? `0${minutes}` : `${minutes}`;
    const seconds = Math.floor(time % 60);
    const formatSeconds = seconds < 10 ? `0${seconds}` : `${seconds}`;
    return `${formatMinutes}:${formatSeconds}`;
  }
  return '00:00';
};

export const AudioPlayer = ({}: AudioPlayerProps) => {
  const { mode } = useThemeMode();
  const { playTrackList, trackOffset, previous, next, first } =
    useActivePlaylistService();
  const audioRef = useRef<HTMLAudioElement>(null);
  const [isPlaying, setIsPlaying] = useState<boolean>(false);
  const [timeProgress, setTimeProgress] = useState<number>(0);
  const [playingMode, setPlayingMode] = useState<PlayMode>(PlayMode.PLAY_ALL);
  const [duration, setDuration] = useState<number>(0);
  const { dataTrack } = useSpecificTrack(
    trackOffset !== undefined ? playTrackList[trackOffset] : undefined
  );
  const { dataAlbum } = useSpecificAlbum(dataTrack?.albumId);
  const { dataGender } = useSpecificGender(dataTrack?.genderId);
  const { dataArtists } = useSpecificArtists(dataTrack?.artists);

  const [mediaSource, setMediaSource] = useState<string>('');
  useEffect(() => {
    setMediaSource(
      dataTrack && dataTrack?.dataId
        ? DataUrlAccess.getUrl(dataTrack?.dataId)
        : ''
    );
  }, [dataTrack, setMediaSource]);
  const backColor = mode('back.100', 'back.800');
  const configButton = {
    borderRadius: 'full',
    backgroundColor: '#00000000',
    _hover: {
      boxShadow: 'outline-over',
      bgColor: 'brand.500',
    },
  };

  useEffect(() => {
    if (!audioRef || !audioRef.current) {
      return;
    }
    if (isPlaying) {
      audioRef.current.play();
    } else {
      audioRef.current.pause();
    }
  }, [isPlaying, audioRef]);

  const onAudioEnded = () => {
    if (playTrackList.length === 0 || isNullOrUndefined(trackOffset)) {
      return;
    }
    if (playingMode === PlayMode.PLAY_ALL_LOOP) {
      if (playTrackList.length == trackOffset + 1) {
        first();
      } else {
        next();
      }
    } else if (playingMode === PlayMode.PLAY_ALL) {
      next();
    } else if (playingMode === PlayMode.PLAY_ONE_LOOP) {
      onSeek(0);
      onPlay();
    }
  };
  const onSeek = (newValue) => {
    console.log(`onSeek: ${newValue}`);
    if (!audioRef || !audioRef.current) {
      return;
    }
    audioRef.current.currentTime = newValue;
  };
  const onPlay = () => {
    if (!audioRef || !audioRef.current) {
      return;
    }
    if (isPlaying) {
      audioRef.current.pause();
    } else {
      audioRef.current.play();
    }
  };
  const onStop = () => {
    if (!audioRef || !audioRef.current) {
      return;
    }
    if (audioRef.current.currentTime == 0 && audioRef.current.paused) {
      // TODO remove curent playing value
    } else {
      audioRef.current.pause();
      audioRef.current.currentTime = 0;
    }
  };
  const onNavigatePrevious = () => {
    previous();
  };
  const onFastRewind = () => {
    if (!audioRef || !audioRef.current) {
      return;
    }
    audioRef.current.currentTime -= 10;
  };
  const onFastForward = () => {
    if (!audioRef || !audioRef.current) {
      return;
    }
    audioRef.current.currentTime += 10;
  };
  const onNavigateNext = () => {
    next();
  };
  const onTypePlay = () => {
    setPlayingMode((value: PlayMode) => {
      if (value === PlayMode.PLAY_ONE) {
        return PlayMode.PLAY_ALL;
      } else if (value === PlayMode.PLAY_ALL) {
        return PlayMode.PLAY_ONE_LOOP;
      } else if (value === PlayMode.PLAY_ONE_LOOP) {
        return PlayMode.PLAY_ALL_LOOP;
      } else {
        return PlayMode.PLAY_ONE;
      }
    });
  };
  /**
   * Call when meta-data is updated
   */
  function onChangeMetadata(): void {
    const seconds = audioRef.current?.duration;
    if (seconds !== undefined) {
      setDuration(seconds);
    }
  }
  const onTimeUpdate = () => {
    if (!audioRef || !audioRef.current) {
      return;
    }
    console.log(`onTimeUpdate ${audioRef.current.currentTime}`);
    setTimeProgress(audioRef.current.currentTime);
  };
  const onDurationChange = (event) => {};
  const onChangeStateToPlay = () => {
    setIsPlaying(true);
  };
  const onChangeStateToPause = () => {
    setIsPlaying(false);
  };
  return (
    <>
      {!isNullOrUndefined(trackOffset) && (
        <Flex
          position="absolute"
          height="150px"
          minHeight="150px"
          paddingY="5px"
          paddingX="10px"
          marginX="15px"
          bottom={0}
          left={0}
          right={0}
          zIndex={1000}
          borderWidth="1px"
          borderColor="brand.900"
          bgColor={backColor}
          borderTopRadius="10px"
          direction="column"
        >
          <Text
            align="left"
            fontSize="20px"
            fontWeight="bold"
            userSelect="none"
            marginRight="auto"
            overflow="hidden"
            noOfLines={1}
          >
            {dataTrack?.name ?? '???'}
          </Text>
          <Text
            align="left"
            fontSize="16px"
            userSelect="none"
            marginRight="auto"
            overflow="hidden"
            noOfLines={1}
          >
            {dataArtists.map((data) => data.name).join(', ')} /{' '}
            {dataAlbum && dataAlbum?.name}
            {dataGender && ` / ${dataGender.name}`}
          </Text>
          <Box width="full" paddingX="15px">
            <Slider
              aria-label="slider-ex-4"
              defaultValue={0}
              value={timeProgress}
              min={0}
              max={duration}
              step={0.1}
              onChange={onSeek}
              focusThumbOnChange={false}
            >
              <SliderTrack bg="gray.200" height="10px" borderRadius="full">
                <SliderFilledTrack bg="brand.600" />
              </SliderTrack>
              <SliderThumb boxSize={6}>
                <Box color="brand.600" as={MdGraphicEq} />
              </SliderThumb>
            </Slider>
          </Box>
          <Flex>
            <Text
              align="left"
              fontSize="16px"
              userSelect="none"
              marginRight="auto"
              overflow="hidden"
              noOfLines={1}
            >
              {formatTime(timeProgress)}
            </Text>
            <Text align="left" fontSize="16px" userSelect="none">
              {formatTime(duration)}
            </Text>
          </Flex>
          <Flex gap="5px">
            <IconButton
              {...configButton}
              aria-label={'Play'}
              icon={
                isPlaying ? (
                  <MdPause size="30px" />
                ) : (
                  <MdPlayArrow size="30px" />
                )
              }
              onClick={onPlay}
            />
            <IconButton
              {...configButton}
              aria-label={'Stop'}
              icon={<MdStop size="30px" />}
              onClick={onStop}
            />
            <IconButton
              {...configButton}
              aria-label={'Previous track'}
              icon={<MdNavigateBefore size="30px" />}
              onClick={onNavigatePrevious}
              marginLeft="auto"
            />
            <IconButton
              {...configButton}
              aria-label={'jump 15sec in past'}
              icon={<MdFastRewind size="30px" />}
              onClick={onFastRewind}
            />
            <IconButton
              {...configButton}
              aria-label={'jump 15sec in future'}
              icon={<MdFastForward size="30px" />}
              onClick={onFastForward}
            />
            <IconButton
              {...configButton}
              aria-label={'Next track'}
              icon={<MdNavigateNext size="30px" />}
              marginRight="auto"
              onClick={onNavigateNext}
            />
            <IconButton
              {...configButton}
              aria-label={'continue to the end'}
              icon={playModeIcon[playingMode]}
              onClick={onTypePlay}
            />
          </Flex>
        </Flex>
      )}

      <audio
        src={mediaSource}
        ref={audioRef}
        //preload={true}
        onPlay={onChangeStateToPlay}
        onPause={onChangeStateToPause}
        onTimeUpdate={onTimeUpdate}
        onDurationChange={onDurationChange}
        onLoadedMetadata={onChangeMetadata}
        autoPlay={true}
        onEnded={onAudioEnded}
      />
    </>
  );
};
