import React, { forwardRef, memo, useMemo } from 'react';
import LinearProgress from '@mui/material/LinearProgress';
import type { LinearProgressProps } from '@mui/material/LinearProgress';
import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
import type { TypographyProps } from '@mui/material/Typography';
import reduce from 'lodash/reduce';
import createClasses, { ClassesProps } from './styles';

const initTextObject = {
  text: '',
  position: ''
};

const textVariant = 'body2';

export interface ProgressBarProps extends Omit<LinearProgressProps, 'color'> {
  /**
   * The background color of the bar.
   */
  color?: ClassesProps['color'];
  /**
   * Texts that can be placed around the component.
   */
  texts?: {
    [key in
      | 'topStart'
      | 'top'
      | 'topEnd'
      | 'right'
      | 'bottomEnd'
      | 'bottom'
      | 'bottomStart'
      | 'left']?: string | number;
  };
  /**
   * Override styles
   */
  classes?: {
    [key in keyof ReturnType<typeof createClasses>]?: string;
  };
}

const ProgressBar = forwardRef((props: ProgressBarProps, ref) => {
  const { texts, value, color, classes } = props;

  const { top, bottom, left, right } = useMemo(
    () =>
      reduce(
        texts,
        (acc, val, originalKey) => {
          if (val) {
            const key = originalKey.replace(/Start|End/, '').toLowerCase();
            acc[key] = {
              text: val.toString(),
              position:
                // Check for the word "Start"
                (originalKey.includes('S') && 'left') ||
                // Check for the word "End"
                (originalKey.includes('E') && 'right') ||
                'center'
            };
          }
          return acc;
        },
        {
          top: initTextObject,
          right: initTextObject,
          bottom: initTextObject,
          left: initTextObject
        } as Record<
          string,
          { text: string; position: TypographyProps['align'] }
        >
      ),
    [texts]
  );

  const styles = createClasses({
    color: color || ''
  });

  return (
    <Grid className={classes?.root}>
      {top.text && (
        <Typography
          variant={textVariant}
          className={`${styles.text} ${styles.marginBottom} ${
            classes?.text || ''
          } ${classes?.marginBottom || ''}`}
          align={top.position}
        >
          {top.text}
        </Typography>
      )}
      <Grid container alignItems="center">
        {left.text && (
          <Typography
            className={`${styles.text} ${styles.rightText} ${
              classes?.text || ''
            }`}
            variant={textVariant}
            align="left"
          >
            {left.text}
          </Typography>
        )}

        <LinearProgress
          ref={ref}
          value={value}
          variant="determinate"
          className={`${styles.progress} ${classes?.progress}`}
          classes={{
            bar1Determinate: `${styles.bar1Determinate} ${classes?.bar1Determinate}`
          }}
        />
        {right.text && (
          <Typography
            className={`${styles.text} ${styles.rightText} ${
              classes?.text || ''
            }`}
            variant={textVariant}
            align="right"
          >
            {right.text}
          </Typography>
        )}
      </Grid>
      {bottom.text && (
        <Typography
          className={`${styles.text} ${styles.marginTop} ${
            classes?.text || ''
          } ${classes?.marginTop || ''}`}
          variant={textVariant}
          align={bottom.position}
        >
          {bottom.text}
        </Typography>
      )}
    </Grid>
  );
});

ProgressBar.defaultProps = {
  color: '#3A5BA2',
  texts: {
    topStart: '',
    top: '',
    topEnd: '',
    right: '',
    bottomEnd: '',
    bottom: '',
    bottomStart: '',
    left: ''
  },
  classes: {}
};

const m = memo(ProgressBar);
export { m as ProgressBar };
