import Page, {PageFlexRow} from "../primitives/page/Page";
import {useCallback, useContext, useEffect, useMemo, useState} from "react";
import RuntimeContext from "../contexts/RuntimeContext";
import {useNavigate} from "react-router";
import LoadingPage from "./LoadingPage";
import DeviceContext from "../contexts/DeviceContext";
import ProgramContext from "../contexts/ProgramContext";
import {Device} from "../models/Devices";
import {Program, subTitleOfProgram} from "../models/Programs";
import {useKey, usePlusMinus} from "../hooks/keyboard";
import {FluffyValue, TitleLine, Value} from "../primitives/misc/Misc";
import Blob, {BlobText, BlobTextLine} from "../primitives/blob/Blob";
import {Icon} from "../primitives/Shared";
import {faClose, faPlay} from "@fortawesome/free-solid-svg-icons";
import {stateString, WorkoutStatus} from "../models/Workouts";
import {Boi} from "../primitives/boi/Boi";
import {useLastState} from "./runtime/hooks";
import {ControlsBoi} from "./runtime/ControlsBoi";
import MessageBoi from "./runtime/MessageBoi";
import ProgramBoi from "./runtime/ProgramBoi";
import MilestoneBoi from "./runtime/MilestoneBoi";
import {useKpm} from "../hooks/kpm";

function PlayPage(): JSX.Element {
  const {active, ready, ended, workout, reset, resume} = useContext(RuntimeContext);
  const navigate = useNavigate();

  useEffect(() => {
    if (!active) {
      resume();
    }
  }, [active, resume]);

  useEffect(() => {
    if (active && ended && workout) {
      navigate(`/workouts/${workout.id}`, {replace: true});
      reset();
    }
  }, [active, ready, ended, workout]);

  if (active && ready && workout === null) {
    return <CreatePlayPage/>;
  }

  if (active && workout !== null) {
    return <RunPlayPage/>;
  }

  return <LoadingPage minimal text="Starter økt"/>;
}

const noProgram: Program = {
  id: "",
  name: "Uten program",
  steps: [{index: 0, values: {}, duration: undefined}],
}

function CreatePlayPage(): JSX.Element {
  const {devices} = useContext(DeviceContext);
  const {programs} = useContext(ProgramContext);
  const {create} = useContext(RuntimeContext);
  const programWithFake = useMemo(() => programs ? [noProgram, ...programs] : null, [programs]);
  const navigate = useNavigate();

  const [device, setDevice] = useState<Device | null>(null);
  const [program, setProgram] = useState<Program | null>(null);

  const [sel, setSel] = usePlusMinus((device ? (program ? 2 : programWithFake?.length) : devices?.length) || 1);

  const confirmSelection = useCallback((idx: number) => {
    if (program && device) {
      if (idx === 0) {
        create({deviceId: device.id, programId: program.id || undefined, test: false})
      } else {
        navigate("/");
      }
    } else if (device && programWithFake) {
      setProgram(programWithFake[idx] || null);
      setSel(0);
    } else if (devices !== null) {
      setDevice(devices[idx] || null);
      setSel(0);
    }
  }, [create, device, program, devices, programWithFake]);

  useKey("Enter", () => {
    confirmSelection(sel);
  }, [confirmSelection, sel]);

  useKey("Escape", () => {
    navigate("/");
  }, []);

  useEffect(() => {
    if (devices && devices.length === 0) {
      navigate("/");
    }
  }, [devices]);

  if (devices === null) {
    return <LoadingPage minimal text="Henter enheter"/>
  } else if (programWithFake === null) {
    return <LoadingPage minimal text="Henter programmer"/>
  }

  return (
    <Page background={"2046"}>
      {device === null && (
        <Boi vertical="center" horizontal="center" style={{fontSize: undefined}}>
          <TitleLine>Velg enhet</TitleLine>
          {devices.map((d, i) => (
            <Blob key={d.id} onClick={() => confirmSelection(i)} color={sel === i ? "indigo" : "gray"}>
              <BlobText>
                <BlobTextLine>{d.name}</BlobTextLine>
                <BlobTextLine secondary>{d.connectionString}</BlobTextLine>
              </BlobText>
            </Blob>
          ))}
        </Boi>
      )}

      {device !== null && program === null && (
        <Boi vertical="center" horizontal="center" style={{fontSize: undefined}}>
          <TitleLine>Velg program</TitleLine>
          {programWithFake.map((p, i) => (
            <Blob key={p.id} onClick={() => confirmSelection(i)} color={sel === i ? "indigo" : "gray"}>
              <BlobText>
                <BlobTextLine>{p.name}</BlobTextLine>
                <BlobTextLine secondary>{subTitleOfProgram(p)}</BlobTextLine>
              </BlobText>
            </Blob>
          ))}
        </Boi>
      )}

      {device && program && (
        <Boi vertical="center" horizontal="center" style={{fontSize: undefined}}>
          <TitleLine>Oppsumering</TitleLine>
          {device && (
            <Blob>
              <BlobText>
                <BlobTextLine>{device.name}</BlobTextLine>
                <BlobTextLine secondary>{device.connectionString}</BlobTextLine>
              </BlobText>
            </Blob>
          )}
          {program && (
            <Blob>
              <BlobText>
                <BlobTextLine>{program.name}</BlobTextLine>
                <BlobTextLine secondary>{subTitleOfProgram(program)}</BlobTextLine>
              </BlobText>
            </Blob>
          )}
          <PageFlexRow>
            {device && program && (
              <>
                <Blob onClick={() => confirmSelection(0)} color={sel === 0 ? "indigo" : "gray"}>
                  <BlobText>
                    <Icon value={faPlay}/> Start
                  </BlobText>
                </Blob>
                <Blob onClick={() => confirmSelection(1)} color={sel === 1 ? "indigo" : "gray"}>
                  <BlobText>
                    <Icon value={faClose}/> Avbryt
                  </BlobText>
                </Blob>
              </>
            )}
          </PageFlexRow>
        </Boi>
      )}
    </Page>
  );
}

function RunPlayPage(): JSX.Element {
  const {workout} = useContext(RuntimeContext);
  const lastState = useLastState();
  const kpm = useKpm();

  if (!workout || workout.status === WorkoutStatus.Created) {
    return <LoadingPage minimal/>;
  }

  return (
    <Page title="YKonsole" background={"2046"}>
      <ControlsBoi/>
      {lastState && (
        <Boi vertical="center" horizontal="left" style={{padding: "0.5vmax", paddingBottom: "0"}}>
          <span style={{fontSize: "125%"}}>
            <FluffyValue raw={lastState} valueKey="time"/>
          </span>
          <FluffyValue raw={lastState} valueKey="calories"/>
          <FluffyValue raw={lastState} valueKey="distance"/>
          <FluffyValue raw={lastState} valueKey="level"/>
          <FluffyValue raw={lastState} valueKey="rpmSpeed"/>
          {kpm > 0 && <FluffyValue raw={kpm} valueKey="kpm"/>}
          <FluffyValue raw={lastState} valueKey="pulse"/>
        </Boi>
      )}
      {workout?.status === WorkoutStatus.Connected && <MessageBoi text="Trykk Enter for å begynne"/>}
      {workout?.status === WorkoutStatus.Stopped && <MessageBoi text="Pause"/>}
      {workout.program && workout.program.steps.length > 0 && <ProgramBoi/>}
      <MilestoneBoi/>
    </Page>
  );
}



export default PlayPage;
