import React, { useState, useEffect } from "react";
import { makeStyles } from "@material-ui/styles";

// This function from @material-ui/styles help create css
const userStyle = makeStyles({
  container: {
    display: "flex",
    justifyContent: "center",
    alignItems: "flex-end",
    height: "100%",
    border: "2px solid lightgray"
  },
  bar: {
    margin: "1px"
  }
});

// Initializes a random array based on props given (min, max, amt)
const initArray = (min, max, amount) => {
  let arr = [];
  for (let i = 0; i < amount; i++)
    arr.push(Math.floor(Math.random() * max) + min);
  return arr;
};

// Main sorting array. Change this for different algorithms.
const BubbleSort = props => {
  // Make our styles first with useStyles()
  const classes = userStyle();
  // useState is used to create "state" variables in function components which have no state.
  // It works like this:
  // const [var, targetMethod] = useState(arg from targetMethod);
  // Object.assign(target, source)  (makes an empty array from initArray return val)
  const [masterArr] = useState(Object.assign([], initArray(1, 100, 50)));
  // "array" var will hold the sorted array
  const [array, setArray] = useState([]);
  // Finds max val in array for scaling bars
  const [maxVal, setMaxVal] = useState(0);
  // sortingIndex is used when drawing the bars.
  const [sortingIndex, setSortingIndex] = useState(0);

  // Use useEffect() in place of componentDidMount() and
  // componentDidUpdate() to handle "side effects".
  // Side effects are modifications to the DOM that you want to
  // do after updating the DOM (render) without having to re-render
  useEffect(() => {
    // "..." means unpack the variable into an array
    setMaxVal(Math.max(...masterArr));
    // Call function which sets array "state" variable
    setArray(masterArr);
    // Create a copy of masterArray for modifying
    let masterCopy = Object.assign([], masterArr);
    Sort(masterCopy);
  }, []);

  // Bubblesort algorithm
  const Sort = arr => {
    for (let i = 0; i < arr.length - 1; i++) {
      for (let j = 0; j < arr.length - (i - 1); j++) {
        setTimeout(() => {
          // Swap if necessary
          if (arr[j] > arr[j + 1]) {
            let tmp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = tmp;
            // Set array to most recent sort
            setArray(Object.assign([], arr));
            // Update sorting index
            setSortingIndex(j);
          }
        }, 10);
      }
    }
  };

  return (
    // JSX tag for doing array mapping and conditional styling
    <>
      <div className={classes.container}>
        {/* Maps each element of array with a value and index*/}
        {array.map((value, index) => (
          // Each bar is just a colored div
          <div
            className={classes.bar}
            style={{
              background: sortingIndex === (index - 1) ? "red" : "green",
              width: `${100 / array.length}%`,
              // Scale height based on maxVal in array
              height: `${(value * 100) / maxVal}%`
            }}
          />
        ))}
      </div>
    </>
  );
};
export default BubbleSort;