import { GetClasses } from '../../typeUtils';
import { makeStyles } from '../../styles';
import { useReducedMotion } from 'framer-motion';
import * as React from 'react';
import clsx from 'clsx';

export const LinearProgressStylesKey = 'ChromaLinearProgress';

export const useStyles = makeStyles(
  (theme) => ({
    root: {
      '--linear-progress-height': '0.25rem',
      '--linear-progress-background-color': theme.palette.black[100],
      '--linear-progress-bar-color': `linear-gradient(135deg,
        ${theme.palette.primary.light} 0%,
        ${theme.palette.primary.main} 22%,
        ${theme.palette.purple[700]} 92%)`,
      backgroundColor: 'var(--linear-progress-background-color)',
      height: 'var(--linear-progress-height)',
      overflow: 'hidden',
      position: 'relative',
    },
    bar: {
      background: 'var(--linear-progress-bar-color)',
      bottom: 0,
      height: 'var(--linear-progress-height)',
      left: 0,
      position: 'absolute',
      top: 0,
      transition: 'transform 0.4s linear',
      width: '100%',
    },
    indeterminate: {
      animation:
        '$chroma-progress-bar-indeterminate 2s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite',
    },
    indeterminateReduced: {
      animation:
        '$chroma-progress-bar-indeterminate 10s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite',
    },
    '@keyframes chroma-progress-bar-indeterminate': {
      '0%': {
        left: '-100%',
        right: '100%',
      },
      '60%': {
        left: '50%',
        right: '-50%',
      },
      '100%': {
        left: '100%',
        right: '-100%',
      },
    },
  }),
  { name: LinearProgressStylesKey }
);

export type LinearProgressClasses = GetClasses<typeof useStyles>;

export interface LinearProgressProps {
  className?: string;
  value?: number;
  variant?: 'determinate' | 'indeterminate';
}

export const LinearProgress: React.FC<LinearProgressProps> = ({
  className,
  variant = 'determinate',
  value = 0,
  ...rootProps
}) => {
  const classes = useStyles({});

  const shouldReduceMotion = useReducedMotion();

  return (
    <div
      className={clsx(classes.root, className)}
      role="progressbar"
      aria-valuenow={variant === 'determinate' ? value : undefined}
      aria-valuemin={variant === 'determinate' ? 0 : undefined}
      aria-valuemax={variant === 'determinate' ? 100 : undefined}
      {...rootProps}
    >
      <div
        className={clsx(
          classes.bar,
          variant === 'indeterminate' && classes.indeterminate,
          shouldReduceMotion && classes.indeterminateReduced
        )}
        style={
          variant === 'determinate'
            ? { transform: `translateX(-${100 - value}%)` }
            : undefined
        }
      />
    </div>
  );
};