import { FC } from 'react';

import { useTranslation } from 'react-i18next';

import PauseIcon from '@material-hu/icons/material/Pause';
import PlayIcon from '@material-hu/icons/material/PlayArrowRounded';
import Box, { BoxProps } from '@material-hu/mui/Box';
import CircularProgress from '@material-hu/mui/CircularProgress';
import IconButton from '@material-hu/mui/IconButton';
import Slider from '@material-hu/mui/Slider';
import { useTheme } from '@material-hu/mui/styles';
import Typography from '@material-hu/mui/Typography';
import useMediaQuery from '@material-hu/mui/useMediaQuery';

import { useAuth } from 'src/contexts/JWTContext';
import { useAudioPlayback } from 'src/hooks/useAudioPlayback';
import { User } from 'src/types/user';
import {
  formatAudioTime,
  formatAudioSliderValue,
  getAudioButtonLabel,
  getNewPlaybackRate,
} from 'src/utils/attachments';

import PlaybackRate from 'src/components/attachment/components/PlaybackRate';

export type AudioProps = BoxProps & {
  messageId?: string | number;
  src: string;
  step?: number;
  duration?: number;
  onPlayError?: (error: unknown) => void;
  onTimeChangeError?: () => void;
  sender?: User;
};

export const Audio: FC<AudioProps> = props => {
  const {
    messageId,
    src,
    step = 0.2,
    duration,
    onPlayError = () => null,
    onTimeChangeError = () => null,
    sender,
  } = props;

  const theme = useTheme();
  const isMatch = useMediaQuery(theme.breakpoints.down('sm'));
  const { t } = useTranslation('attachments');
  const { user: loggedUser } = useAuth();

  const {
    audioRef,
    currentTime,
    isPlaying,
    isLoading,
    playbackRate,
    hasBeenPlayed,
    safeDuration,
    durationSeconds,
    togglePlay,
    handleEnded,
    handleTimeUpdate,
    handleSlideChange,
    handleKeyDown,
    handleLoadStart,
    handleCanPlayThrough,
    handleLoadedMetadata,
    handleRateChange,
    getCurrentTime,
  } = useAudioPlayback({
    src,
    step,
    duration,
    messageId,
    onPlayError,
    onTimeChangeError,
  });

  const onRateChange = () => {
    const newRate = getNewPlaybackRate(playbackRate);
    handleRateChange(newRate);
  };

  const getSliderAriaValueText = () =>
    formatAudioSliderValue(currentTime, safeDuration);

  const isLoggedUser = sender ? sender.id === loggedUser?.id : false;
  const showPlaybackRate = !!sender;

  return (
    <Box
      aria-label={t('audio_player') as string}
      onKeyDown={handleKeyDown}
      sx={{ position: 'relative' }}
    >
      <audio
        src={src}
        controls={false}
        ref={audioRef}
        onEnded={handleEnded}
        onTimeUpdate={handleTimeUpdate}
        onLoadStart={handleLoadStart}
        onCanPlayThrough={handleCanPlayThrough}
        onLoadedMetadata={handleLoadedMetadata}
      />
      <Box
        sx={{
          display: 'flex',
          flexDirection: 'row',
          alignItems: 'center',
        }}
      >
        {showPlaybackRate && isLoggedUser && (
          <PlaybackRate
            sender={sender}
            hasBeenPlayed={hasBeenPlayed}
            playbackRate={playbackRate}
            handleRateChange={onRateChange}
          />
        )}
        <IconButton
          onClick={togglePlay}
          disabled={isLoading}
          aria-label={getAudioButtonLabel(isLoading, isPlaying)}
          size="small"
          sx={{
            mr: 2,
            pl: 0,
          }}
        >
          {isLoading && (
            <CircularProgress
              color="inherit"
              sx={{
                width: '35px !important',
                height: '35px !important',
              }}
            />
          )}
          {!isLoading && (
            <>
              {!isPlaying && <PlayIcon fontSize="large" />}
              {isPlaying && <PauseIcon fontSize="large" />}
            </>
          )}
        </IconButton>
        <Slider
          aria-label={t('audio_slider')}
          aria-valuetext={getSliderAriaValueText()}
          name="audio-slider"
          step={step}
          min={0}
          max={durationSeconds}
          value={currentTime}
          onChange={handleSlideChange}
          sx={{
            minWidth: isMatch ? 'auto' : '200px',
            width: isMatch ? '160px' : 'auto',
          }}
        />
        {showPlaybackRate && !isLoggedUser && (
          <PlaybackRate
            sender={sender}
            hasBeenPlayed={hasBeenPlayed}
            playbackRate={playbackRate}
            handleRateChange={onRateChange}
          />
        )}
      </Box>
      <Typography
        color="textSecondary"
        variant="caption"
        noWrap
        sx={{
          position: 'absolute',
          bottom: '-4px',
          left: isLoggedUser ? '124px' : '60px',
        }}
      >
        {formatAudioTime(getCurrentTime())}
      </Typography>
    </Box>
  );
};

export default Audio;
