import { Popup } from "semantic-ui-react";
import * as React from "react";

interface Props {
  /** Lista a ser renderizada na barra de percentual */
  readings: Readings[];
  /** Tamanho minimo da barra */
  minWidth: number;
  /** Número de casas decimais do percentual total */
  decimals?: number;
  /** Popup do percentual total */
  mainPopup?: any;
}

interface State {
  filteredReadings: Readings[];
  offsetRows: Readings[];
  totalReadings: number;
}

interface Readings {
  value: number;
  color: string;
  width?: number;
  popup?: any;
}

export default class MagaMultiProgressBar extends React.Component<
  Props,
  State
> {
  static defaultProps = { decimals: 2, minWidth: 2 };

  constructor(props: Props) {
    super(props);

    this.state = {
      filteredReadings: [],
      offsetRows: [],
      totalReadings: 0,
    };
  }

  componentDidMount() {
    this.setComponentState(this.props);
  }

  setComponentState = (props: Props) => {
    const { minWidth, readings } = props;
    const filteredReadings = readings.filter(({ value }) => value > 0);
    const totalReadings = filteredReadings.length;
    const offsetRows = filteredReadings.filter(({ value }) => value < minWidth);
    this.setState({ filteredReadings, offsetRows, totalReadings });
  };

  UNSAFE_componentWillReceiveProps(nextProps: Props) {
    this.setComponentState(nextProps);
  }

  getWidth = (value: number) => {
    const { minWidth } = this.props;
    const { offsetRows, totalReadings } = this.state;
    const totalWithoutMinWidth = offsetRows.reduce(
      (total, reading) => total + (minWidth - reading.value),
      0
    );
    const offsetDiff = totalReadings - offsetRows.length;

    if (offsetDiff === 0) {
      return minWidth;
    }

    const result = Math.round(value - totalWithoutMinWidth / offsetDiff);

    return result > minWidth ? result : minWidth;
  };

  getWidthTotal = (readings: Readings[]) => {
    return readings.reduce((total, reading) => total + reading.width!, 0);
  };

  getPercentageTotal = () => {
    return this.state.filteredReadings.reduce(
      (total, { value }) => total + value,
      0
    );
  };

  getReadingsWithWidth = () => {
    return this.state.filteredReadings.map((reading) => ({
      ...reading,
      width: this.getWidth(reading.value),
    }));
  };

  render() {
    const { decimals, mainPopup, minWidth } = this.props;
    const { filteredReadings } = this.state;
    let { readings } = this.props;
    let percentageTotal = 0;
    let widthGraduation = 100;

    if (filteredReadings.length) {
      readings = this.getReadingsWithWidth();
      percentageTotal = this.getPercentageTotal();

      const totalWidth = this.getWidthTotal(readings);
      const percentageDiff = percentageTotal - totalWidth;
      widthGraduation = totalWidth;

      if (percentageDiff !== 0) {
        const maxValue = readings.reduce(
          (max, p) => (p.width! > max ? p.width! : max),
          readings[0].width!
        );

        if (maxValue > minWidth) {
          const indexReading = readings.findIndex(
            (reading) => reading.width! === maxValue
          );

          const width = Math.round(
            readings[indexReading].width! + percentageDiff
          );

          readings[indexReading] = { ...readings[indexReading], width };
          widthGraduation = this.getWidthTotal(readings);
        }
      }
      if (percentageTotal > 100) {
        readings.forEach((x) => {
          x.width = Math.floor((x.width! * 100) / Math.floor(percentageTotal));
        });
      }
    }

    const bar = (color: string, width: number) => (
      <div
        className="bar"
        style={{ backgroundColor: color, width: `${width}%` }}
      />
    );

    const percentBar = (percentage: number) => (
      <div className="percent-bar">
        <div>{percentage.toFixed(decimals)}%</div>
        <span>|</span>
      </div>
    );

    const bars = (
      <>
        <div className="graduation" style={{ width: `${widthGraduation}%` }}>
          {!mainPopup ? (
            percentBar(percentageTotal)
          ) : (
            <Popup
              trigger={percentBar(percentageTotal)}
              content={mainPopup.value}
              className="with-popup"
              position="top center"
              {...mainPopup.props}
            />
          )}
        </div>
        <div className="bars">
          {readings.map((item: Readings, i: number) => {
            const { color, popup, value, width } = item;

            if (value > 0) {
              return popup ? (
                <Popup
                  key={i}
                  trigger={bar(color, width!)}
                  content={popup.value}
                  className="with-popup"
                  position="bottom center"
                  {...popup.props}
                />
              ) : (
                <div key={i}>{bar(color, width!)}</div>
              );
            }

            return null;
          })}
        </div>
      </>
    );

    return <div className="multiprogress-bar">{bars}</div>;
  }
}
