import { Theme, useTheme } from "@mui/material";
import React, { useCallback, useEffect, useState } from "react";
import Editor from "ventilation/Editor";
import PageContainer from "./PageContainer";
import EditorSidebar from "ventilation/EditorSidebar";
import EditorHeader from "ventilation/EditorHeader";
import { pond } from "protobuf-ts/pond";
import { loadPlaceable, Placeable } from "ventilation/drawable/Placeable";
import { Component } from "models";
// import { useRouteMatch } from "react-router";
// import { MatchParams } from "navigation/Routes";
import { useMineAPI } from "hooks";
import { Sensor } from "ventilation/drawable/Sensor";
import { useParams } from "react-router-dom";
import { makeStyles } from "@mui/styles";
import { useGlobalState } from "providers";

const useStyles = makeStyles((theme: Theme) => {
  return ({
    header: {
      width: "100%",
      height: theme.spacing(7),
      background: "rgba(25, 25, 25, 1)",
      margin: 0,
      padding: 0,
      display: "flex",
      alignItems: "center",
      borderBottom: "1px solid rgb(75, 75, 75)"
    },
    middleButtons: {
      display: "flex",
      alignItems: "center",
      margin: "auto"
    },
    divider: {
      height: "42px",
      width: "2px",
      margin: theme.spacing(1)
    },
    editor: {
      // border: "1px solid red",
      width: "100%",
      height: "auto",
      margin: 0,
      padding: 0
    }
  });
});

enum Mode {
  NORMAL,
  MOVE,
  ADD,
  DELETE
}

export default function Ventilation() {
  const classes = useStyles();
  const [width, setWidth] = useState(0);
  const [height, setHeight] = useState(0);
  const [mode, setMode] = useState(Mode.NORMAL);
  // const match = useRouteMatch<MatchParams>();
  const mineKey = useParams<{ mineKey: string }>()?.mineKey ?? "";
  // const mineKey = match.params.mineKey;
  const undoRef = React.useRef(null);
  const redoRef = React.useRef(null);
  const saveRef = React.useRef(null);
  const addBlockRef = React.useRef(null);
  const theme = useTheme();
  const [devices, setDevices] = useState<pond.Device[]>([]);
  const [components, setComponents] = useState<Component[]>([]);
  const [blocks, setBlocks] = useState<Placeable[]>([]);
  const [mine, setMine] = useState<pond.MineSettings>(pond.MineSettings.create());
  const mineAPI = useMineAPI();
  const [loading, setLoading] = useState(false);
  const [permissions, setPermissions] = useState<pond.Permission[]>([]);
  const [componentPreferences, setComponentPreferences] = useState<
    Map<string, pond.MineComponentPreferences>
  >(new Map());
  const [sensors, setSensors] = useState<Sensor[]>([]);
  const [componentDevices, setComponentDevices] = useState<Map<string, number>>(new Map());
  const [{as}] = useGlobalState();

  const handleResize = (node: any) => {
    setHeight(node.getBoundingClientRect().height);
    setWidth(node.getBoundingClientRect().width);
  };

  const pageContainer = useCallback((node: any) => {
    if (node) {
      handleResize(node);
      window.addEventListener("resize", () => handleResize(node), false);
    }
  }, []);

  useEffect(() => {
    if (loading) return;
    if (!mineKey) return;
    setLoading(true);
    mineAPI
      .getMine(mineKey, as)
      .then((resp: { data: pond.IGetMineResponse | undefined; }) => {
        if (resp.data && resp.data.mine && resp.data.mine.settings) {
          let data = pond.GetMineResponse.create(resp.data);
          let perms: pond.Permission[] = [];
          data.permissions.forEach(p => {
            if (typeof p === "string" && p === "PERMISSION_READ") {
              perms.push(pond.Permission.PERMISSION_READ);
            } else if (typeof p === "string" && p === "PERMISSION_WRITE") {
              perms.push(pond.Permission.PERMISSION_WRITE);
            } else if (typeof p === "string" && p === "PERMISSION_SHARE") {
              perms.push(pond.Permission.PERMISSION_SHARE);
            } else if (typeof p === "string" && p === "PERMISSION_USERS") {
              perms.push(pond.Permission.PERMISSION_USERS);
            }
          });
          setPermissions(perms);
          setMine(resp.data.mine.settings);
          setDevices(data.devices);
          let newBlocks: Placeable[] = [];
          if (resp.data.mine?.settings?.placeables)
            resp.data.mine?.settings?.placeables.forEach(p => {
              let placeable = loadPlaceable(p);
              newBlocks.push(placeable as Placeable);
            });
          setBlocks(newBlocks);
          let prefs = new Map(Object.entries(data.componentPreferences));
          setComponentPreferences(prefs);
          setComponentDevices(new Map(Object.entries(data.componentDevices)));
          let components: Component[] = [];
          if (resp.data.components)
            resp.data.components.forEach(component => {
              components.push(Component.any(component));
            });
          setComponents(components);
        }
      })
      .finally(() => {
        setLoading(false);
      });
    // eslint-disable-next-line
  }, [mineKey, mineAPI]);

  return (
    // TODO: why does padding have to be -2 to fit the page?
    <PageContainer padding={-2}>
      <div style={{ height: "100%", overflow: "hidden" }}>
        <EditorHeader
          setMode={setMode}
          undoRef={undoRef}
          redoRef={redoRef}
          saveRef={saveRef}
          blocks={blocks}
          setBlocks={setBlocks}
          devices={devices}
          setDevices={setDevices}
          components={components}
          mine={mine}
          setMine={setMine}
          permissions={permissions}
          setPermissions={setPermissions}
          componentPreferences={componentPreferences}
          sensors={sensors}
        />
        {
          <div style={{ display: "flex", flexDirection: "row", height: "100%" }}>
            <EditorSidebar
              addBlockRef={addBlockRef}
              devices={devices}
              setDevices={setDevices}
              components={components}
              setComponents={setComponents}
              mine={mine}
              setMine={setMine}
              mineComponentPreferences={componentPreferences}
              setMineComponentPreferences={setComponentPreferences}
            />
            <div ref={pageContainer} className={classes.editor}>
              <Editor
                width={width}
                height={height - parseInt(theme.spacing(7), 10)}
                mode={mode}
                undoRef={undoRef}
                redoRef={redoRef}
                saveRef={saveRef}
                addBlockRef={addBlockRef}
                devices={devices}
                blocks={blocks}
                setBlocks={setBlocks}
                components={components}
                setComponents={setComponents}
                componentPreferences={componentPreferences}
                setComponentPreferences={setComponentPreferences}
                sensors={sensors}
                setSensors={setSensors}
                loading={loading}
                componentDevices={componentDevices}
              />
            </div>
          </div>
        }
      </div>
    </PageContainer>
  );
}
