import { memo } from '../../lib/teact/teact';

import type { GlobalState } from '../../global/types';

import { selectTabState } from '../../global/selectors';
import buildClassName from '../../util/buildClassName';
import buildStyle from '../../util/buildStyle';

import useSelector from '../../hooks/data/useSelector';
import useShowTransition from '../../hooks/useShowTransition';

import styles from './Sparkles.module.scss';

function selectIsHeavyModalOpen(global: GlobalState) {
  const tabState = selectTabState(global);
  return Boolean(tabState.giftCraftModal || tabState.giftCraftSelectModal);
}

type ButtonParameters = {
  preset: 'button';
};

type ProgressParameters = {
  preset: 'progress';
};

type PresetParameters = ButtonParameters | ProgressParameters;

type OwnProps = {
  className?: string;
  style?: string;
  noAnimation?: boolean;
} & PresetParameters;

const SYMBOL = '✦';
const ANIMATION_DURATION = 5;

// Values are in percents
const BUTTON_POSITIONS = [{
  x: 20,
  y: 0,
  size: 100,
  durationShift: 10,
}, {
  x: 15,
  y: 15,
  size: 75,
  durationShift: 70,
}, {
  x: 10,
  y: 35,
  size: 75,
  durationShift: 90,
}, {
  x: 20,
  y: 70,
  size: 125,
  durationShift: 30,
}, {
  x: 40,
  y: 10,
  size: 125,
  durationShift: 0,
}, {
  x: 45,
  y: 60,
  size: 75,
  durationShift: 60,
}, {
  x: 60,
  y: -10,
  size: 100,
  durationShift: 20,
}, {
  x: 55,
  y: 40,
  size: 75,
  durationShift: 60,
}, {
  x: 70,
  y: 65,
  size: 100,
  durationShift: 90,
}, {
  x: 80,
  y: 10,
  size: 75,
  durationShift: 30,
}, {
  x: 80,
  y: 45,
  size: 125,
  durationShift: 0,
}];
const PROGRESS_POSITIONS = generateRandomProgressPositions(100);

const Sparkles = ({
  className,
  style,
  noAnimation,
  ...presetSettings
}: OwnProps) => {
  const isHeavyModalOpen = useSelector(selectIsHeavyModalOpen);

  const { ref, shouldRender } = useShowTransition<HTMLDivElement>({
    isOpen: !isHeavyModalOpen,
    withShouldRender: true,
    noMountTransition: true,
  });

  if (!shouldRender) return undefined;

  if (presetSettings.preset === 'button') {
    return (
      <div
        ref={ref}
        className={buildClassName(styles.root, styles.button, className, noAnimation && styles.noAnimation)}
        style={style}
      >
        {BUTTON_POSITIONS.map((position) => {
          const shiftX = Math.cos(Math.atan2(-50 + position.y, -50 + position.x)) * 100;
          const shiftY = Math.sin(Math.atan2(-50 + position.y, -50 + position.x)) * 100;
          return (
            <div
              className={styles.symbol}
              style={buildStyle(
                `top: ${position.y}%`,
                `left: ${position.x}%`,
                `--_duration-shift: ${(-position.durationShift / 100) * ANIMATION_DURATION}s`,
                `--_shift-x: ${shiftX}%`,
                `--_shift-y: ${shiftY}%`,
                `scale: ${position.size}%`,
              )}
              aria-hidden="true"
            >
              {SYMBOL}
            </div>
          );
        })}
      </div>
    );
  }

  if (presetSettings.preset === 'progress') {
    return (
      <div
        ref={ref}
        className={buildClassName(styles.root, styles.progress, className)}
        style={style}
      >
        {PROGRESS_POSITIONS.map((position) => {
          return (
            <div
              className={styles.symbol}
              style={buildStyle(
                `top: ${position.y}%`,
                `left: ${position.x}%`,
                `--_shift-x: ${position.velocityX}%`,
                `--_shift-y: ${position.velocityY}%`,
                `scale: ${position.scale}%`,
                `--_duration-shift: ${(-position.durationShift / 100) * ANIMATION_DURATION}s`,
              )}
              aria-hidden="true"
            >
              {SYMBOL}
            </div>
          );
        })}
      </div>
    );
  }

  return undefined;
};

function generateRandomProgressPositions(count: number) {
  const positions = [];
  for (let i = 0; i < count; i++) {
    positions.push({
      x: Math.random() * 100,
      y: Math.random() * 100,
      velocityX: (Math.random() * 5 + 15) * 100,
      velocityY: (Math.random() * 10 - 5) * 100,
      scale: (Math.random() * 0.5 + 0.5) * 100,
      durationShift: Math.random() * 100,
    });
  }
  return positions;
}

export default memo(Sparkles);
