import { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { green, blue } from '@mui/material/colors';

import Logo from '../Logo';
import { styled, useTheme } from '../Theme';

/**
 * ActivityIndicator is used when we want to tell the user the request they made on the UI will take time.
 * @typedef {{
 *  interval?: number;
 *  messages: string[];
 * } & import('react').ComponentPropsWithoutRef<"div"> } ActivityIndicatorProps
 */

/**
 * @description ActivityIndicator is used when we want to tell the user the request they made on the UI will take time.
 * @param {ActivityIndicatorProps} props
 * @returns {JSX.Element}
 */
export default function ActivityIndicator({ messages = ['Loading data...'], interval = 3000, ...rest }) {
  const [index, setIndex] = useState(0);
  const { palette } = useTheme();

  useEffect(() => {
    const timer = setInterval(() => {
      setIndex((index + 1) % messages.length);
    }, interval);

    return () => {
      clearTimeout(timer);
    };
  });

  return (
    <Div {...rest}>
      <div className="pm-loader-container">
        <div className="pm-loader-text">
          <p>{messages[index]}</p>
        </div>
        <div className="pm-loader-atoms">
          <Logo style={{ transform: 'scale(0.6)' }} showText={false} />
          <Orbit size={56} orbitColor={green[500]} atomColor={green[500]} duration={1} />
          <Orbit size={80} orbitColor={blue[800]} atomColor={blue[800]} duration={1.5} />
          <Orbit size={100} orbitColor={palette.grey[900]} atomColor={palette.grey[900]} />
        </div>
      </div>
    </Div>
  );
}

ActivityIndicator.propTypes = {
  interval: PropTypes.number,
  messages: PropTypes.arrayOf(PropTypes.string.isRequired),
};

const Div = styled('div')`
  && {
    box-sizing: border-box;
    padding: 20px;
    width: 100%;
    height: 100%;
    min-height: 360px;
    z-index: 100;
    transition: opacity 0.5s linear;
    display: flex;
    align-items: center;
    flex-direction: column;
    justify-content: center;
  }

  .pm-loader-text {
    color: ${({ theme }) => theme.palette.grey[900]};
    font-size: 14px;
    text-align: center;
    position: relative;
    height: 70px;
    -webkit-user-select: none;
  }

  .pm-loader-container {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    flex-direction: column;
    justify-content: center;
    flex: 1;
  }

  .pm-loader-atoms {
    width: 100px;
    height: 100px;
    display: flex;
    position: relative;
    align-items: center;
    justify-content: center;
  }
`;

function Orbit({ size, orbitColor, atomColor, duration = 2, ...rest }) {
  return (
    <OrbitRoot $duration={duration} style={{ width: size, height: size, border: `1px solid ${orbitColor}` }} {...rest}>
      <div style={{ background: atomColor }} />
    </OrbitRoot>
  );
}

Orbit.propTypes = {
  size: PropTypes.number.isRequired,
  orbitColor: PropTypes.string.isRequired,
  atomColor: PropTypes.string.isRequired,
  duration: PropTypes.number,
};

const OrbitRoot = styled('div')`
  @keyframes orbit {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }

  position: absolute;
  border-radius: 50%;
  animation: orbit ${({ $duration }) => $duration}s infinite;
  animation-timing-function: linear;
  transform-origin: center;

  > div {
    position: absolute;
    top: 50%;
    width: 6px;
    height: 6px;
    transform: translateX(-50%);
    border-radius: 50%;
  }
`;
