import React from "react";
import { useState, useRef } from "react";
import { default as MonacoEditor } from "@monaco-editor/react";
import { withRouter } from "react-router-dom";
import { Button, Grid } from "@material-ui/core";
import Blockly from "blockly/core";
import Divider from "@material-ui/core/Divider";
import { saveAs } from "file-saver";
import Drawer from "@material-ui/core/Drawer";
import Sidebar from "./Sidebar";
import Dialog from "../Dialog";
import SaveIcon from "./SaveIcon";
import store from "../../store";

const CodeEditor = (props) => {
  //const [filehandle, setFileHandle] = useState();
  const [fileContent, setFileContent] = useState("");
  const [progress, setProgress] = useState(false);
  // const [id, setId] = useState("");
  const [open, setOpen] = useState(false);
  const [error, setError] = useState("");
  const editorRef = useRef(null);
  const [autoSave, setAutoSave] = useState(false);
  const [time, setTime] = useState(null);
  const [value, setValue] = useState("");
  const [resetDialog, setResetDialog] = useState(false);

  const compile = () => {
    setProgress(true);
    const data = {
      board: process.env.REACT_APP_BOARD,
      sketch: editorRef.current.getValue(),
    };
    fetch(`${process.env.REACT_APP_COMPILER_URL}/compile`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    })
      .then((response) => response.json())
      .then((data) => {
        if (data.code === "Internal Server Error") {
          setProgress(false);
          setOpen(true);
          setError(data.message);
        }
        setProgress(false);
        const result = data.data.id;
        //setId(result);
        const filename = "sketch";
        window.open(
          `${process.env.REACT_APP_COMPILER_URL}/download?id=${result}&board=${process.env.REACT_APP_BOARD}&filename=${filename}`,
          "_self"
        );
      })
      .catch((err) => {
        console.log(err);
      });
  };

  const saveIno = () => {
    var filename = "sketch";
    var code = editorRef.current.getValue();

    filename = `${filename}.ino`;
    var blob = new Blob([code], { type: "text/plain;charset=utf-8" });
    saveAs(blob, filename);
  };

  const openIno = async () => {
    const [myFileHandle] = await window.showOpenFilePicker();
    //setFileHandle(myFileHandle);

    const file = await myFileHandle.getFile();
    const contents = await file.text();
    setFileContent(contents);
  };

  const toggleDrawer = (anchor, open) => (event) => {
    if (
      event.type === "keydown" &&
      (event.key === "Tab" || event.key === "Shift")
    ) {
      return;
    }

    setOpen(false);
  };

  const resetCode = () => {
    const resetCode = `
#include <senseBoxIO.h> //needs to be always included
    
void setup () {
             
}
              
void loop() {
              
}`;

    editorRef.current.setValue(resetCode);
  };

  const resetTimeout = (id, newID) => {
    clearTimeout(id);
    return newID;
  };

  const editValue = (value) => {
    setTime(resetTimeout(time, setTimeout(saveValue, 400)));
    setValue(value);
  };

  const saveValue = () => {
    localStorage.setItem("ArduinoCode", value);
    setAutoSave(true);
    setTimeout(() => setAutoSave(false), 1000);
  };

  const getBlocklyCode = () => {
    var code = store.getState().workspace.code.arduino;
    editorRef.current.setValue(code);
  };

  return (
    <div>
      <Grid container spacing={2}>
        <Drawer
          anchor={"bottom"}
          open={open}
          onClose={toggleDrawer("bottom", false)}
        >
          <h2
            style={{
              color: "#4EAF47",
              paddingLeft: "1rem",
              paddingRight: "1rem",
            }}
          >
            {Blockly.Msg.drawer_ideerror_head}
          </h2>
          <p
            style={{
              color: "#4EAF47",
              paddingLeft: "1rem",
              paddingRight: "1rem",
            }}
          >
            {Blockly.Msg.drawer_ideerror_text}
          </p>
          <Divider style={{ backgroundColor: "white" }} />
          <p
            style={{
              backgroundColor: "black",
              color: "#E47128",
              padding: "1rem",
            }}
          >
            {" "}
            {`${error}`}{" "}
          </p>
        </Drawer>
        <Grid item lg={8} md={8}>
          <div style={{ display: "flex", alignItems: "center" }}>
            <h1>Code Editor</h1>
            <SaveIcon loading={autoSave} />
          </div>

          <MonacoEditor
            height="80vh"
            onChange={(value) => {
              editValue(value);
            }}
            defaultLanguage="cpp"
            defaultValue={
              localStorage.getItem("ArduinoCode")
                ? localStorage.getItem("ArduinoCode")
                : `
#include <senseBoxIO.h> //needs to be always included
      
void setup () {
               
}
                
void loop() {
                
}`
            }
            value={fileContent}
            onMount={(editor, monaco) => {
              editorRef.current = editor;
            }}
          />
        </Grid>
        <Grid item lg={4} md={4}>
          <Button
            style={{ padding: "1rem", margin: "1rem" }}
            variant="contained"
            color="primary"
            onClick={() => compile()}
          >
            Kompilieren
          </Button>
          <Button
            style={{ padding: "1rem", margin: "1rem" }}
            variant="contained"
            color="primary"
            onClick={() => saveIno()}
          >
            {Blockly.Msg.codeeditor_save_code}
          </Button>
          <Button
            style={{ padding: "1rem", margin: "1rem" }}
            variant="contained"
            color="primary"
            onClick={() => openIno()}
          >
            {Blockly.Msg.codeeditor_open_code}
          </Button>
          <Button
            style={{ padding: "1rem", margin: "1rem" }}
            variant="contained"
            color="primary"
            onClick={() => setResetDialog(true)}
          >
            {Blockly.Msg.codeeditor_reset_code}
          </Button>
          <Button
            style={{ padding: "1rem", margin: "1rem" }}
            variant="contained"
            color="primary"
            onClick={() => getBlocklyCode()}
          >
            {Blockly.Msg.codeeditor_blockly_code}
          </Button>
          <Sidebar />
          <Dialog
            style={{ zIndex: 9999999 }}
            fullWidth
            maxWidth={"sm"}
            open={progress}
            title={"Code wird kompiliert"}
            content={""}
          >
            <div>{Blockly.Msg.codeeditor_compile_progress}</div>
          </Dialog>{" "}
          <Dialog
            open={resetDialog}
            title={Blockly.Msg.resetDialog_headline}
            content={Blockly.Msg.resetDialog_text}
            onClose={() => {
              setResetDialog(false);
            }}
            onClick={() => {
              setResetDialog(false);
            }}
            button={Blockly.Msg.button_cancel}
          >
            {" "}
            <div style={{ marginTop: "10px" }}>
              <Button
                variant="contained"
                color="primary"
                onClick={() => {
                  resetCode();
                  setResetDialog(false);
                }}
              >
                Zurücksetzen
              </Button>
            </div>
          </Dialog>
        </Grid>
      </Grid>
    </div>
  );
};

export default withRouter(CodeEditor);
