// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import classNames from 'classnames';
import React, { useCallback, useState } from 'react';
import { animated, useSpring } from '@react-spring/web';
import type { LocalizerType } from '../types/Util.std.ts';
import { useReducedMotion } from '../hooks/useReducedMotion.dom.ts';

const SPRING_CONFIG = {
  mass: 0.5,
  tension: 350,
  friction: 20,
  velocity: 0.01,
};

type Props = {
  // undefined if not playing
  playbackRate: number | undefined;
  variant: 'message-outgoing' | 'message-incoming' | 'mini-player';
  onClick: () => void;
  visible?: boolean;
  i18n: LocalizerType;
};

export function PlaybackRateButton({
  playbackRate,
  variant,
  visible = true,
  i18n,
  onClick,
}: Props): React.JSX.Element {
  const [isDown, setIsDown] = useState(false);
  const reducedMotion = useReducedMotion();

  // oxlint-disable-next-line react-hooks/exhaustive-deps -- FIXME
  const [animProps] = useSpring(
    {
      immediate: reducedMotion,
      config: SPRING_CONFIG,
      to: isDown ? { scale: 1.3 } : { scale: visible ? 1 : 0 },
    },
    [visible, isDown]
  );

  // Clicking button toggle playback
  const onButtonClick = useCallback(
    (event: React.MouseEvent) => {
      event.stopPropagation();
      event.preventDefault();

      onClick();
    },
    [onClick]
  );

  // Keyboard playback toggle
  const onButtonKeyDown = useCallback(
    (event: React.KeyboardEvent) => {
      if (event.key !== 'Enter' && event.key !== 'Space') {
        return;
      }
      event.stopPropagation();
      event.preventDefault();

      onClick();
    },
    [onClick]
  );

  const playbackRateLabels: { [key: number]: string } = {
    1: i18n('icu:MessageAudio--playbackRate1'),
    1.5: i18n('icu:MessageAudio--playbackRate1p5'),
    2: i18n('icu:MessageAudio--playbackRate2'),
    0.5: i18n('icu:MessageAudio--playbackRatep5'),
  };

  const label = playbackRate
    ? playbackRateLabels[playbackRate]?.toString()
    : undefined;

  return (
    <animated.div style={animProps}>
      <button
        type="button"
        className={classNames(
          'PlaybackRateButton',
          `PlaybackRateButton--${variant}`
        )}
        onClick={onButtonClick}
        onKeyDown={onButtonKeyDown}
        onMouseDown={() => setIsDown(true)}
        onMouseUp={() => setIsDown(false)}
        onMouseLeave={() => setIsDown(false)}
        aria-label={label}
        tabIndex={0}
      >
        {label}
      </button>
    </animated.div>
  );
}

const playbackRates = [1, 1.5, 2, 0.5];

PlaybackRateButton.nextPlaybackRate = (currentRate: number): number => {
  // cycle through the rates
  // oxlint-disable-next-line typescript/no-non-null-assertion
  return playbackRates[
    (playbackRates.indexOf(currentRate) + 1) % playbackRates.length
  ]!;
};
