import { forwardRef, useImperativeHandle, useState, useEffect } from "react";
import {
  FormControl,
  InputLabel,
  Select,
} from "@material-ui/core";
import api from "../../../services/vehiclesAPI";
import TaskRunner from "../../../utils/taskRunner";
import { AllECUsCommand } from "../../Controls/SendDiagnosticCommand";
import useStyles from "../../useStyles";
import { useStatusContext } from "../../Contexts/StatusContext";
import { useUserContext } from "../../Contexts/UserContext";
import unionIntersect from "../../../utils/unionIntersect";

const commands = [
  { val: "remote_reset", displayname: "Remote Reset" },
];

async function getECUsByVINs(vins, token) {
  return new Promise((resolve, reject) => {
    const taskRunner = new TaskRunner(10, vins.length);

    const task = (vin) => {
      return async () => api.getECUs({ vin, unique: true }, token)
        .then((result) => {
          if (result.total === 0) {
            reject([]);
          }
          return result.data.map(({ ecu }) => ecu);
        })
        .catch(() => reject([]));
    }

    vins.forEach((vin) => {
      taskRunner.push(task(vin));
    });

    taskRunner.onComplete().then((results) => {
      const ecus = unionIntersect(...results);
      resolve(ecus.map(ecu => ({ ecu })));
    });
  });
}

export default forwardRef(({
  ids,
  idCSV,
}, ref) => {
  const [ecus, setECUs] = useState([{ ecu: "TBOX" }]);
  const [currentECU, setCurrentECU] = useState("");
  const [validateECUs, setValidateECUs] = useState(false);
  const [command, setCommand] = useState("");
  const classes = useStyles();
  const { setMessage } = useStatusContext();
  const { token: { idToken: { jwtToken: token } } } = useUserContext();

  useImperativeHandle(ref, () => ({
    async submit() {
      if (!validateECUs) {
        return Promise.reject("Invalid ECUs found, cannot submit");
      }

      return api.sendDiagnosticCommand(ids, {
        command,
        ecu_name: currentECU,
      }, token)
        .then(() => {
          setMessage(`Sent ${command} command to ${ids.length} vehicles.`);
        })
        .catch(() => {
          setMessage(`Failed to send ${command} command.`);
        });
    }
  }));

  const handleSelectCommand = (e) => {
    setCommand(e.target.value);
  };

  useEffect(() => {
    async function fetchData() {
      setValidateECUs(false);
      const ecus = await getECUsByVINs(ids, token);
      setECUs(() => [{ ecu: "TBOX" }, ...ecus]); // TBOX is a hardcoded ECU
    }
    fetchData();
  }, [ids, token]);

  useEffect(() => {
    setValidateECUs(true);
  }, [ecus]);

  return (
    <div>
      <p>
        Attempt to send a vehicle diagnostic command to the following VINs: {idCSV}.
      </p>
      <AllECUsCommand classes={classes} ecus={ecus} currentECU={currentECU} setCurrentECU={setCurrentECU} />

      <FormControl className={classes.formControl} variant="outlined" size="small" margin="normal">
        <InputLabel htmlFor="send-command" className={classes.whiteBackground}>
          Diagnostic Command
        </InputLabel>
        <Select native variant="outlined"
          inputProps={{
            name: "send-command",
            id: "send-command",
          }}
          onChange={handleSelectCommand}
        >
          {commands.map((command, index) => (
            <option key={index} value={command.val}>
              {command.displayname}
            </option>
          ))}
        </Select>
      </FormControl>
    </div>
  );
});