import React, {
  useEffect,
  useMemo,
  useCallback,
  useRef,
  useState,
  useContext,
} from "react";
import { FabricJSCanvas, useFabricJSEditor } from "fabricjs-react";
import { fabric } from "fabric";
import { DockSidebar } from "Components/DockSidebar";
import { ActionButtons } from "Components/ActionButtons";
import MkdSDK from "Utils/MkdSDK";
import { Stack } from "Utils/utils";
import { EstimateModal } from "Components/EstimateModal";
import * as XLSX from "xlsx";
import { BuildCanvasFromLocalModal } from "Components/BuildCanvasFromLocalModal";
import { GlobalContext } from "../../globalContext";
import { clearClone, clone } from "Utils/DockBuilderUtils/clone";
import {
  edgeDetection,
  handleEdgeDetection,
  handleIntersection,
} from "Utils/DockBuilderUtils";
import {
  CanvasModes,
  deleteIcon,
  DockPanelCategories,
  edgeSnapThreshold,
  nintyDeg,
  oneEightyDeg,
  oneFeet,
  rotateIcon,
  scaleFactor,
  twoSeventyDeg,
} from "Utils/constants";
import {
  reScaleXY,
  resolveHeight,
  resolveWidth,
} from "Utils/DockBuilderUtils/edgeDetection";
import { DeleteIcon, RotateIcon } from "Assets/svgs";
import { capitalize } from "Utils/helper";

const sdk = new MkdSDK();
const stack = new Stack();

export const DockBuilder = () => {
  let clipboard = null;
  let mouseDownPoint = null;
  let shiftKeyDown = false;
  window.counter = 0;
  let prevPointer = null;
  let isDragging = false;
  let isZoomed = false;
  let startX, startY;

  const { dispatch } = useContext(GlobalContext);
  const { editor, onReady } = useFabricJSEditor({ selection: true });

  const canvasModeRef = useRef(null);
  const fileRef = useRef();
  const imageRef = useRef();

  const editorMemo = useMemo(() => editor?.canvas, [editor?.canvas]);
  // const { dispatch } = React.useContext( AuthContext );
  const [objHovered, setObjHovered] = useState(false);
  const [selectedItems, setSelectedItems] = useState([]);
  const [estimateLoading, setEstimateLoading] = useState(false);
  const [showEstimateModal, setShowEstimateModal] = useState(false);
  const [showBuildCanvasFromLocalModal, setShowBuildCanvasFromLocalModal] =
    useState(false);
  const [initialLoad, setInitialLoad] = useState(true);
  const [linesAdded, setLinesAdded] = useState(false);
  const [dockImage, setDockImage] = useState(null);
  const [editorReady, setEditorReady] = useState(false);
  const [dockLabel, setDockLabel] = useState(null);
  const [dockDimensions, setDockDimensions] = useState(null);

  const deleteImg = document.createElement("img");
  deleteImg.src = deleteIcon;
  const rotateImg = document.createElement("img");
  rotateImg.src = rotateIcon;

  const onEstimateModalClose = useCallback(() => {
    setShowEstimateModal(false);
  }, [showEstimateModal]);

  const onEstimateModalOpen = useCallback(() => {
    const ext = "png";
    const base64 = editorMemo.toDataURL({
      format: ext,
      enableRetinaScaling: true,
    });
    setDockImage(base64);
    setShowEstimateModal(true);
  }, [showEstimateModal, editorMemo, dockImage]);

  // const onAddRect = useCallback( () => {
  //   editor?.canvas?.add( rect );
  //   window.counter++;
  //   // newleft += 200;
  // }, [ editor ] );

  const toJSON = () => {
    // TODO: download the json file
    // TODO: get json of editor content
    // TODO: Ensure dockData is included in the json
    // TODO: save the json to the local storage as dock
    // TODO: name the file as paradise_dock_<timestamp here>.dock
  };

  const uploadFile = (e) => {
    // TODO: Our own upload the file we must have downloaded previously
    // TODO: extract the json from the file
    // TODO: load the json to the editor
    // TODO: render all
  };

  const downloadImage = useCallback(() => {
    const ext = "png";
    // Generate base64 image of the canvas
    const base64 = editorMemo.toDataURL({
      format: ext,
      enableRetinaScaling: true,
    });
    // Download the image
    const anchor = document.createElement("a");
    const timestamp = Date.now();
    anchor.href = base64;
    anchor.download = `paradise_dock_snapshot_${timestamp}.${ext}`;
    anchor.click();

    // Extract dockData from all objects (excluding snapClone)
    const json = editorMemo.toJSON(["dockData", "snapClone"]);
    const dockDataArr = (json.objects || [])
      .filter((object) => object.dockData && !object.snapClone)
      .map((object) => object.dockData);
    if (dockDataArr.length > 0) {
      // Download as Excel
      const worksheet = XLSX.utils.json_to_sheet(dockDataArr);
      const workbook = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(workbook, worksheet, "Dock Data");
      XLSX.writeFile(workbook, `paradise_dock_data_${timestamp}.xlsx`);
    }
  }, [editorMemo]);

  const renderBg = useCallback(() => {
    const imageURL =
      "https://s3.us-east-2.amazonaws.com/com.nds.images/download.png";

    new fabric.Image.fromURL(
      imageURL,
      function (img) {
        img.set({
          scaleX: editorMemo.width / img.width,
          scaleY: editorMemo.height / img.height,
        });
        editorMemo.setBackgroundImage(img);
        editorMemo.renderAll();
        // updateModifications( true, )
      },
      {
        crossOrigin: "anonymous",
      }
    );
  }, [editorMemo]);

  const downloadExcel = useCallback((data) => {
    const worksheet = XLSX.utils.json_to_sheet(data);
    const workbook = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(workbook, worksheet, "Selected Items");
    XLSX.writeFile(workbook, "Paradise_dock_selected_items.xlsx");
  }, []);

  function updateZoom(opt) {
    let delta = opt.e.deltaY;
    let pointer = editorMemo.getPointer(opt.e);
    let zoom = editorMemo.getZoom();

    if (delta > 0) {
      zoom *= 1.1;
    } else {
      zoom /= 1.1;
    }
    if (zoom > 5) zoom = 5;
    if (zoom < 1) zoom = 1;
    // console.log( zoom )
    // editorMemo.setBackgroundImageStretch=false
    var vpt = editorMemo.viewportTransform;
    if (zoom === 1) {
      vpt[4] = 0;
      vpt[5] = 0;
      editorMemo.selection = true;
      this.isZoomed = false;
    }
    if (zoom > 1) {
      this.isZoomed = true;
    }

    fabric.util.animate({
      startValue: editorMemo.getZoom(),
      endValue: zoom,
      // duration: 0,
      onChange: function (value) {
        editorMemo.zoomToPoint({ x: pointer.x, y: pointer.y }, value);
      },
      fps: 1080,
    });
    opt.e.preventDefault();
    opt.e.stopPropagation();
  }

  function handleZoomMouseDown(options) {
    var pointer = editorMemo.getPointer(options.e, true);
    mouseDownPoint = new fabric.Point(pointer.x, pointer.y);
    if (options.target === null && this.isZoomed) {
      editorMemo.upperCanvasEl.style.cursor = "grabbing";
      editorMemo.selection = false;
      // this.lastPosX = options.e.movementX;
      // this.lastPosY = options.e.movementY;
      this.lastPosX = options.e.clientX;
      this.lastPosY = options.e.clientY;

      //
    }
    // else if ( options.target !== null && this.isZoomed ) {
    //   var activeObject = editorMemo.getActiveObject();
    //   if ( activeObject ) {
    //     activeObject.lockMovementX = true;
    //     activeObject.lockMovementY = true;
    //     activeObject.lockScalingX = true;
    //     activeObject.lockScalingY = true;
    //   }
    // }
  }

  const handleZoomMouseUp = useCallback(() => {
    editorMemo.defaultCursor = "default";
    mouseDownPoint = null;
    editorMemo.selection = true;
  }, [editor]);

  function handleZoomMouseMove(options) {
    if (options.target === null && mouseDownPoint && this.isZoomed) {
      editorMemo.selection = false;
      editorMemo.upperCanvasEl.style.cursor = "grabbing";

      var delta = new fabric.Point(options.e.movementX, options.e.movementY);
      editorMemo.relativePan(delta);
      editorMemo.viewportTransform[4] = Math.max(
        Math.min(editorMemo.viewportTransform[4], 0),
        editorMemo.getWidth() - editorMemo.getWidth() * editorMemo.getZoom()
      );
      editorMemo.viewportTransform[5] = Math.max(
        Math.min(editorMemo.viewportTransform[5], 0),
        editorMemo.getHeight() - editorMemo.getHeight() * editorMemo.getZoom()
      );

      // var vpt = this.viewportTransform;
      // vpt[ 4 ] += options.e.clientX - this.lastPosX;
      // vpt[ 5 ] += options.e.clientY - this.lastPosY;
      requestAnimationFrame(function () {
        editorMemo.renderAll();
        this.requestRenderAll();
      });
      // this.lastPosX = options.e.movementX;
      // this.lastPosY = options.e.movementY;
      // this.lastPosX = options.e.clientX;
      // this.lastPosY = options.e.clientY;
    }
  }

  const addEdgeDetectionClone = useCallback(
    (options) => {
      objectMoving = true;
      if (options) {
        const selectedObj = options.target.setCoords();
        editorMemo.defaultCursor = "grabbing";
        if (
          selectedObj.dockData &&
          selectedObj.dockData.itemName === DockPanelCategories.Accessories
        ) {
          return;
        }

        editorMemo.forEachObject((obj) => {
          const pointer = { x: options.e.clientX, y: options.e.clientY };

          if (obj === selectedObj) return;
          // canvas.setCursor('grabbing');
          // // console.log(pointer.x, pointer.y);
          if (!obj.snapClone && obj.type === "image") {
            // // console.log( pointer, prevPointer )
            if (
              prevPointer &&
              (prevPointer.x !== pointer.x || prevPointer.y !== pointer.y)
            ) {
              switch (true) {
                case edgeDetection(selectedObj, obj, "left"):
                  clone(selectedObj, editorMemo, obj, "left");
                  break;
                case edgeDetection(selectedObj, obj, "right"):
                  clone(selectedObj, editorMemo, obj, "right");
                  break;
                case edgeDetection(selectedObj, obj, "top"):
                  clone(selectedObj, editorMemo, obj, "top");
                  break;
                case edgeDetection(selectedObj, obj, "bottom"):
                  clone(selectedObj, editorMemo, obj, "bottom");
                  break;
                case edgeDetection(selectedObj, obj, "neutral"):
                  clearClone(editorMemo);
                  break;
                default:
                // console.log( "edge detection switch default" )
              }
              // prevPointer = null;
            }
            prevPointer = pointer;
            // // console.log( pointer, prevPointer )
          }
          // if ( edgeDetection( selectedObj, obj, "left" ) ) {
          //   clone( selectedObj, editorMemo, obj, "left" )
          // } else {
          //   // clearClone( editorMemo )
          // }

          // if ( edgeDetection( selectedObj, obj, 'right' ) ) {
          //   clone( selectedObj, editorMemo, obj, "right" )

          // } else {
          //   // clearClone( editorMemo )
          // }

          // if ( edgeDetection( selectedObj, obj, 'top' ) ) {
          //   clone( selectedObj, editorMemo, obj, "top" )

          // } else {
          //   // clearClone( editorMemo )
          // }

          // if ( edgeDetection( selectedObj, obj, 'bottom' ) ) {
          //   clone( selectedObj, editorMemo, obj, "bottom" )
          // } else {
          //   // clearClone( editorMemo )
          // }
        });
      }
    },
    [editor, editorMemo]
  );

  const horizontalIndicatorLines = (newTop, objTop) => {
    editorMemo.getObjects("line").forEach((obj) => {
      if (obj.testLine) {
        editorMemo.remove(obj);
      }
    });

    let line = new fabric.Line([0, newTop, editorMemo.getWidth(), newTop], {
      stroke: "#AAAAAA",
      testLine: true,
      // strokeDashArray: [ 5 ],
    });
    let line2 = new fabric.Line([0, objTop, editorMemo.getWidth(), objTop], {
      stroke: "#AAAAAA",
      testLine: true,
      // strokeDashArray: [ 5 ],
    });
    editorMemo.add(line);
    editorMemo.add(line2);
    editorMemo.renderAll();
  };
  const verticleIndicatorLines = (newLeft, objLeft) => {
    editorMemo.getObjects("line").forEach((obj) => {
      if (obj.testLine) {
        editorMemo.remove(obj);
      }
    });

    let line = new fabric.Line([newLeft, 0, newLeft, editorMemo.getHeight()], {
      stroke: "#AAAAAA",
      testLine: true,
      // strokeDashArray: [ 5 ],
    });
    let line2 = new fabric.Line([objLeft, 0, objLeft, editorMemo.getWidth()], {
      stroke: "#AAAAAA",
      testLine: true,
      // strokeDashArray: [ 5 ],
    });
    editorMemo.add(line);
    editorMemo.add(line2);
    editorMemo.renderAll();
  };

  function edgeDetectionAndSnap(options) {
    if (this.isZoomed) {
      return;
    }

    // TODO: Edge detection and snap to object within snap range
    // TODO: Detect if the object is within the snap range of the selected object
    // TODO: detect if the selected object contains dockData and dockData contains itemName of DockPanelCategories.Accessories || DockPanelCategories.BoatLift2 || DockPanelCategories.BoatLift4
    // TODO: handle rotation of 0, 90, 180, 270 degrees

    editorMemo.defaultCursor = "default";
    prevPointer = null;
    clearClone(editorMemo);
  }

  const showHighlight = useCallback(
    (event) => {
      if (event.target) {
        if (event.target.type === "image") {
          setObjHovered(true);
          // console.log(event.target.dockData)
          if (
            event.target &&
            event.target.dockData &&
            event.target.dockData.image
          ) {
            imageRef.current.src = event.target.dockData.image;
            setDockLabel(
              `${
                event.target.dockData.materials
                  ? capitalize(event.target.dockData.itemName)
                  : event.target.dockData.itemName
              } (${
                event.target.dockData.materials
                  ? event.target.dockData.materials
                  : event.target.dockData.model
              })`
            );
            setDockDimensions(
              `${event.target.dockData.width}' x ${event.target.dockData.length}'`
            );
          } else if (
            event.target &&
            event.target.dockData &&
            event.target.dockData.thumbnail
          ) {
            setDockLabel(
              `${capitalize(event.target.dockData.itemName)} (${
                event.target.dockData.name
              })`
            );
            setDockDimensions(
              `${event.target.dockData.width}' x ${event.target.dockData.length}'`
            );
            imageRef.current.src = event.target.dockData.thumbnail;
          }
        }
      }
      if (!event.target && objHovered) {
        setObjHovered(false);
        setDockLabel(null);
        setDockDimensions(null);
        setDockDimensions(null);
        imageRef.current.src = "";
      }
    },
    [objHovered]
  );

  const hideHighlight = useCallback(() => {
    if (objHovered) {
      setObjHovered(false);
      setDockLabel(null);
      setDockDimensions(null);
      imageRef.current.src = "";
    }
  }, [objHovered]);

  const updateModifications = useCallback(
    (savehistory, event) => {
      if (savehistory === true) {
        if ((event && event === "update") || event.target.dockData) {
          const json = editor?.canvas?.toJSON(["dockData", "snapClone"]);
          const data = JSON.stringify(json);
          stack.updateStack(data);

          updateLocalstore();
        }
      }
    },
    [selectedItems, editor]
  );

  const updateLocalstore = useCallback(() => {
    const json = editor?.canvas?.toJSON(["dockData", "snapClone"]);
    const newObjects = json.objects
      .filter((object) => !object.snapClone)
      .filter(Boolean);
    json.objects = newObjects;
    const items = json.objects
      .map((object) => {
        if (object.dockData && !object.snapClone) {
          return object.dockData;
        }
      })
      .filter(Boolean);
    setSelectedItems(() => [...items]);

    const data = JSON.stringify(json);
    localStorage.setItem("dock", data);
  }, [editor, selectedItems]);

  const onUndoClick = useCallback(() => {
    const undoResult = stack.undo();
    if (undoResult && undoResult.currentState) {
      editorMemo.loadFromJSON(undoResult.currentState, () => {
        editorMemo.renderAll();
      });
    }
  }, [editorMemo]);

  const onRedoClick = useCallback(() => {
    const redoResult = stack.redo();
    if (redoResult && redoResult.currentState) {
      // currentState is an array, get the first element
      const state = Array.isArray(redoResult.currentState)
        ? redoResult.currentState[0]
        : redoResult.currentState;
      if (state) {
        editorMemo.loadFromJSON(state, () => {
          editorMemo.renderAll();
        });
      }
    }
  }, [editorMemo]);

  const onPrintScreen = useCallback(() => {
    // Save current background
    const originalBgColor = editorMemo.backgroundColor;
    const originalBgImage = editorMemo.backgroundImage;

    // Set background to white for printing
    editorMemo.setBackgroundColor(
      "#fff",
      editorMemo.renderAll.bind(editorMemo)
    );
    editorMemo.setBackgroundImage(null, editorMemo.renderAll.bind(editorMemo));

    // Give time for background to update
    setTimeout(() => {
      const dataUrl = editorMemo.toDataURL({
        format: "png",
        enableRetinaScaling: true,
      });
      const printWindow = window.open("", "_blank");
      if (printWindow) {
        printWindow.document.write(
          '<html><head><title>Print Canvas</title></head><body style="margin:0"><img src="' +
            dataUrl +
            '" style="width:100vw;max-width:100%"/></body></html>'
        );
        printWindow.document.close();
        printWindow.focus();
        printWindow.onload = function () {
          printWindow.print();
          printWindow.close();
        };
      }
      // Restore original background
      editorMemo.setBackgroundColor(
        originalBgColor,
        editorMemo.renderAll.bind(editorMemo)
      );
      if (originalBgImage) {
        editorMemo.setBackgroundImage(
          originalBgImage,
          editorMemo.renderAll.bind(editorMemo)
        );
      }
    }, 200);
  }, [editorMemo]);

  const CopySelection = () => {
    // TODO: Copy selection
    const activeObject = editorMemo.getActiveObject();
    if (activeObject) {
      activeObject.clone(function (cloned) {
        clipboard = cloned;
      });
    }
  };

  const PasteSelection = () => {
    // TODO: Paste selection
    if (clipboard) {
      clipboard.clone(function (clonedObj) {
        // Offset the pasted object so it's visible
        clonedObj.set({
          left: (clonedObj.left || 0) + 20,
          top: (clonedObj.top || 0) + 20,
          evented: true,
        });
        editorMemo.add(clonedObj);
        editorMemo.setActiveObject(clonedObj);
        editorMemo.renderAll();
      });
    }
  };

  const onDeleteSelection = () => {
    const activeObject = editorMemo.getActiveObject();
    if (activeObject) {
      editorMemo.remove(activeObject);
      editorMemo.discardActiveObject();
      editorMemo.renderAll();
      updateModifications(true, { target: activeObject });
    }
  };

  const addLines = useCallback(() => {
    // Initiate a line instance
    const editorHeight = editorMemo.getHeight();
    const division = editorHeight / oneFeet;

    if (!linesAdded) {
      let initialFt = 8;
      let multiplier = 1;
      for (let i = division - 3; i > 0; i--) {
        if (multiplier > division - 4) {
          break;
        }
        let line = new fabric.Line(
          [0, oneFeet * i, editorMemo.getWidth(), oneFeet * i],
          {
            stroke: "#AAAAAA",
            strokeDashArray: [5],
          }
        );

        let text = new fabric.Text(`${initialFt * multiplier}ft`, {
          // stroke: '#000000',
          fill: "#AAAAAA",
          fontSize: 18,
          left: editorMemo.getWidth() - 40,
          top: oneFeet * i,
        });

        multiplier++;
        // Render the rectangle in canvas
        editorMemo.add(line).sendToBack(line);
        editorMemo.add(text).sendToBack(text);
        editorMemo.renderAll();
      }
      setLinesAdded(true);
    }
  }, [editorMemo, linesAdded]);

  const removeLines = useCallback(() => {
    editorMemo.getObjects("line").forEach((line) => {
      editorMemo.remove(line);
    });
    editorMemo.getObjects("text").forEach((text) => {
      editorMemo.remove(text);
    });
    setLinesAdded(false);
  }, [editorMemo, linesAdded]);

  const onCloseBuildFromLocalModal = useCallback(() => {
    setShowBuildCanvasFromLocalModal(false);

    dispatch({
      type: "DOCK_LOADING",
      payload: false,
    });
    setInitialLoad(false);
  }, [editorMemo, showBuildCanvasFromLocalModal, dispatch, initialLoad]);
  function renderIcon(icon) {
    return function renderIcon(ctx, left, top, styleOverride, fabricObject) {
      var size = this.cornerSize;
      ctx.save();
      ctx.translate(left, top);
      ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle));
      ctx.drawImage(icon, -size / 2, -size / 2, size, size);
      ctx.restore();
    };
  }
  function deleteObject(eventData, transform) {
    var target = transform.target;
    var canvas = target.canvas;
    canvas.remove(target);
    canvas.requestRenderAll();
  }

  useEffect(() => {
    if (editor) {
      editorMemo.backgroundColor = "#011e23";
      editorMemo.enableRetinaScaling = false;

      // Use hardware acceleration
      // editorMemo.renderOnAddRemove = false;
      editorMemo.skipOffscreen = true;
      // Lower render quality setting
      fabric.devicePixelRatio = 1;
      fabric.Group.prototype.hasControls = true;
      fabric.Group.prototype.snapAngle = 45;
      fabric.Group.prototype.snapThreshold = 5;
      fabric.Group.prototype.stroke = "#0f75bc";
      fabric.Object.prototype.snapAngle = 45;
      // Optimize object rendering
      fabric.Object.prototype.objectCaching = true;

      fabric.Object.prototype.snapThreshold = 5;
      fabric.Object.prototype.setControlsVisibility({
        tl: false, //top-left
        mt: false, // middle-top
        tr: true, //top-right
        ml: false, //middle-left
        mr: false, //middle-right
        bl: false, // bottom-left
        mb: false, //middle-bottom
        br: false, //bottom-right
        mtr: false, // rotate icon
      });
      // fabric.Object.prototype.controls.deleteControl = new fabric.Control( {
      //   x: -0.8,
      //   y: -1,
      //   offsetY: 16,
      //   offsetX: 16,
      //   cursorStyle: 'pointer',
      //   mouseUpHandler: deleteObject,
      //   render: renderIcon( deleteImg ),
      //   cornerPadding: 0,
      //   cornerSize: 24
      // } );
      fabric.Object.prototype.controls.tr = new fabric.Control({
        x: 0.5,
        y: -0.5,
        cursorStyle: "rotate",
        offsetY: -16,
        offsetX: 16,
        cornerPadding: 0,
        actionHandler: fabric.controlsUtils.rotationWithSnapping,
        cursorStyleHandler: fabric.controlsUtils.rotationStyleHandler,
        withConnection: true,
        render: renderIcon(rotateImg),
        cornerSize: 20,
        actionName: "rotate",
        sizeX: 40,
        sizeY: 40,
        touchSizeX: 40,
        touchSizeY: 40,
      });
      fabric.Object.prototype.hasControls = true;
      fabric.Object.prototype.lockScalingX = true;
      fabric.Object.prototype.lockScalingY = true;
      fabric.Object.prototype.cornerSize = 5;
      fabric.Line.prototype.hasBorders = false;
      fabric.Line.prototype.cornerSize = 0;
      fabric.Line.prototype.borderColor = "transparent";
      fabric.Line.prototype.hasRotatingPoint = false;
      fabric.Line.prototype.hasControls = false;
      fabric.Line.prototype.lockRotation = true;
      fabric.Line.prototype.hoverCursor = "default";
      fabric.Line.prototype.selectable = false;
      fabric.Line.prototype.lockMovementX = true;
      fabric.Line.prototype.lockMovementY = true;
      fabric.Text.prototype.hasBorders = false;
      fabric.Text.prototype.cornerSize = 0;
      fabric.Text.prototype.borderColor = "transparent";
      fabric.Text.prototype.hasRotatingPoint = false;
      fabric.Text.prototype.hoverCursor = "default";
      fabric.Text.prototype.selectable = false;
      fabric.Text.prototype.hasControls = false;
      fabric.Text.prototype.lockRotation = true;
      fabric.Text.prototype.lockMovementX = true;
      fabric.Text.prototype.lockMovementY = true;

      // fabric.Text.prototype.viewportCenter = true
      setEditorReady(true);
      editorMemo.setHeight(window.innerHeight);
      editorMemo.setWidth(window.innerWidth);
      fabric.Object.prototype.cornerColor = "#B9C0D4";

      renderBg();
      addLines();

      // Intersection
      // TODO: Edge detection and snap to object within snap range
      editorMemo.on("object:moving", edgeDetectionAndSnap);

      editorMemo.on("mouse:over", showHighlight);
      editorMemo.on("mouse:out", hideHighlight);
      editorMemo.on("object:modified", (e) => updateModifications(true, e));
      editorMemo.on("object:added", (e) => updateModifications(true, e));

      // Listen for the delete key event
      document.onkeydown = (event) => {
        if (event.keyCode === 46) {
          // 46 is the keyCode for the delete key
          onDeleteSelection();
        }
      };

      const savedDock = localStorage.getItem("dock")
        ? JSON.parse(localStorage.getItem("dock"))
        : null;
      if (savedDock) {
        if (initialLoad) {
          setShowBuildCanvasFromLocalModal(true);
        }
      } else if (initialLoad) {
        setInitialLoad(false);
        dispatch({
          type: "DOCK_LOADING",
          payload: false,
        });
      }
    }
  }, [editor]);

  useEffect(() => {
    if (editor) {
      const handleResize = () => {
        // let canvas = canvasRef.current;
        editorMemo.setWidth(window.innerWidth);
        editorMemo.setHeight(window.innerHeight);
        editorMemo.setBackgroundImage(editorMemo.backgroundImage, (bgImage) => {
          bgImage.set({
            scaleX: editorMemo.width / bgImage.width,
            scaleY: editorMemo.height / bgImage.height,
          });
        });
        removeLines();
        addLines();
        editorMemo.renderAll();
      };
      window.addEventListener("resize", handleResize);
      handleResize();
      return () => {
        window.removeEventListener("resize", handleResize);
      };
    }
  }, []);

  return (
    <div className={`relative`}>
      <>
        <DockSidebar
          onDownloadImage={downloadImage}
          onDownloadFile={toJSON}
          onUploadFile={uploadFile}
          fileRef={fileRef}
          editor={editorMemo}
          updateModifications={updateModifications}
          selectedItems={selectedItems}
          onEstimateModalOpen={onEstimateModalOpen}
        />

        <FabricJSCanvas className={`floor-canvas`} onReady={onReady} />

        <ActionButtons
          className={`absolute w-fit top-4 right-8`}
          onCopy={CopySelection}
          onPaste={PasteSelection}
          onRedoClick={onRedoClick}
          onUndoClick={onUndoClick}
          onPrintScreen={onPrintScreen}
          onDeleteSelection={onDeleteSelection}
        />

        <div
          className={`rounded w-[10.875rem] absolute top-0 inset-x-0 m-auto ${
            objHovered ? "" : "hidden"
          }`}
        >
          {dockLabel ? (
            <div
              className={`w-full shadow text-white text-center font-medium text-[1.125rem] leading-[1.6875rem] tracking-[2%] font-['Rajdhani']`}
            >
              {dockLabel}
            </div>
          ) : null}

          <img
            ref={imageRef}
            src=''
            alt=''
            width={174}
            height={116}
            className={`rounded relative ${objHovered ? "" : "hidden"}`}
          />

          {dockDimensions ? (
            <div
              className={`w-full shadow text-white text-center font-medium text-[1.125rem] leading-[1.6875rem] tracking-[2%] font-['Rajdhani']`}
            >
              {dockDimensions}
            </div>
          ) : null}
        </div>
      </>

      <EstimateModal
        loading={estimateLoading}
        modalCloseClick={onEstimateModalClose}
        showEstimateModal={showEstimateModal}
        dockImage={dockImage}
        selectedItems={selectedItems}
      />
      <BuildCanvasFromLocalModal
        modalCloseClick={onCloseBuildFromLocalModal}
        showBuildCanvasFromLocalModal={showBuildCanvasFromLocalModal}
        editor={editorMemo}
      />
    </div>
  );
};
