import {useContext, useEffect, useMemo, useState} from "react";
import RuntimeContext from "../../contexts/RuntimeContext";
import {WorkoutStatus} from "../../models/Workouts";
import {faPause, faPlay} from "@fortawesome/free-solid-svg-icons";
import {useKey, usePlusMinus} from "../../hooks/keyboard";
import {Boi} from "../../primitives/boi/Boi";
import {TitleLine} from "../../primitives/misc/Misc";
import Blob, {BlobText} from "../../primitives/blob/Blob";
import {Icon} from "../../primitives/Shared";
import {useLastState} from "./hooks";
import {IconDefinition} from "@fortawesome/fontawesome-svg-core";
import MessageBoi from "./MessageBoi";

interface Option {
  icon?: IconDefinition
  text?: string
  warning?: boolean
  onClick(): void
}

const skipMessages = ["Ikke hopp over", "Hopp over straks", "Hopp over nå"];

export function ControlsBoi() {
  const {workout, disconnect, start, stop, setLevel, skip} = useContext(RuntimeContext);
  const lastState = useLastState();

  const [mode, setMode] = useState<"default" | "level" | "skip">("default");
  const [nextSkip, setNextSkip] = useState(-1);
  const [lastTime, setLastTime] = useState(0);

  const options: Option[] = useMemo(() => {
    if (!workout) return [];

    const isStopped = workout.status === WorkoutStatus.Connected || workout.status === WorkoutStatus.Stopped;

    const btnList: Option[] = [];
    if (isStopped) {
      btnList.push({icon: faPlay, onClick: start})
    }

    if (workout.status === WorkoutStatus.Started) {
      btnList.push({icon: faPause, onClick: stop});

      if (workout.program) {
        const text = nextSkip > 0 ? `Hopper om ${nextSkip - lastTime} sek.` : "Hopp over steg";

        btnList.push({text, warning: nextSkip >= 0, onClick: () => setMode("skip")})
      } else {
        btnList.push({text: "Motstand", onClick: () => setMode("level")});
      }
    }

    if (isStopped) {
      btnList.push({text: "Avslutt", onClick: disconnect});
    }

    return btnList;
  }, [workout, start, stop, disconnect, skip, nextSkip, lastTime]);

  let length = options.length;
  if (mode === "level") length = 32;
  if (mode === "skip") length = 3;

  const [sel, setSel] = usePlusMinus(length);

  useKey("Enter", () => {
    if (mode !== "default") {
      if (mode === "level") {
        setLevel(sel + 1);
      } else {
        if (sel === 1) {
          setNextSkip(lastTime + 60 - (lastTime % 60));
        } else if (sel === 2) {
          setNextSkip(0);
        } else {
          setNextSkip(-1);
        }
      }

      setSel(0);
      setMode("default");
    } else {
      if (options[sel]) {
        options[sel].onClick();
      }
    }

    setSel(0);
  }, [options, lastTime, sel]);

  useKey("Escape", () => {
    if (!workout) return;

    const isStopped = workout.status === WorkoutStatus.Connected || workout.status === WorkoutStatus.Stopped;

    if (isStopped) {
      disconnect();
    }

  }, [workout, disconnect]);

  useEffect(() => {
    if (lastState?.level && mode === "level") {
      setSel(lastState.level - 1);
    }
  }, [mode]);

  useEffect(() => {
    if (lastState?.time) {
      setLastTime(lastState.time!);
    }
  }, [lastState]);

  useEffect(() => {
    if (nextSkip !== -1 && (nextSkip === 0 || nextSkip <= lastTime)) {
      setNextSkip(-1);
      skip();
    }
  }, [lastTime, nextSkip]);

  if (mode === "level") {
    return <MessageBoi text={`${sel + 1} +/-`}/>;
  }

  if (mode === "skip") {
    return <MessageBoi text={`${skipMessages[sel]} +/-`}/>;
  }

  return (
    <Boi vertical="top" horizontal="right" style={{fontSize: "2vmax"}}>
      {options.map((o, i) => (
        <Blob key={i} color={(o.warning && lastTime % 2 === 0) ? "yellow" : (sel === i ? "indigo" : "gray")} onClick={o.onClick}>
          <BlobText>
            {o.icon && <Icon value={o.icon}/>} {o.text}
          </BlobText>
        </Blob>
      ))}
    </Boi>
  );
}
