'use client';

import { Graphics, Stage, Text } from '@pixi/react';
import { Graphics as PixiGraphics } from '@pixi/graphics';
import { MouseEvent, WheelEvent, useCallback, useEffect, useState } from 'react';
import TileControls, { EditTool, Tool, defaultColors } from './TileControls';
import { Box } from '@mantine/core';
import { TextStyle } from 'pixi.js';

interface SquareEdit {
  x: number;
  y: number;
  color: string;
}

export default function TileGrid() {
  // Offset height of navbar from window height
  const height = window ? window.innerHeight - 70 : 0;
  // Offset width of layout padding from window width
  const width = window ? window.innerWidth : 0;

  const [zoom, setZoom] = useState(1);
  const [gridSize, setGridSize] = useState({ width: width * 2, height: height * 2 });
  const [mouseDown, setMouseDown] = useState(false);
  const [lastPosition, setLastPosition] = useState({ x: -width / 2, y: -height / 2 });
  const [position, setPosition] = useState({ x: -width / 2, y: -height / 2 });
  const [tool, setTool] = useState<Tool>(Tool.HAND);
  const [editTool, setEditTool] = useState<EditTool>(EditTool.SQUARE);
  const [colors, setColors] = useState<string[]>(defaultColors);
  const [selectedColor, setSelectedColor] = useState<number>(0);
  const [edits, setEdits] = useState<SquareEdit[]>([]);

  useEffect(() => {
    if (window) {
      // window.addEventListener(
      //   'wheel',
      //   (event) => {
      //     event.preventDefault();
      //   },
      //   { passive: false }
      // );
      // // Disable right click context menu
      // window.addEventListener(
      //   'contextmenu',
      //   (event) => {
      //     event.preventDefault();
      //   },
      //   { passive: false }
      // );
    }
  }, []);

  const drawGrid = useCallback(
    (g: PixiGraphics) => {
      g.clear();
      // Draw dot in the corner of each tile
      for (let x = 0; x < gridSize.width; x += 32 * zoom) {
        for (let y = 0; y < gridSize.height; y += 32 * zoom) {
          g.beginFill(0xffffff, 0.5);
          g.drawCircle(x, y, 1);
          g.endFill();
        }
      }
    },
    [gridSize, zoom]
  );

  const drawEdits = useCallback(
    (g: PixiGraphics) => {
      g.clear();
      edits.forEach((edit) => {
        g.beginFill(parseInt(edit.color.replace('#', ''), 16));
        g.drawRect(edit.x * 32 * zoom, edit.y * 32 * zoom, 32 * zoom, 32 * zoom);
        g.endFill();
      });
    },
    [edits, zoom]
  );

  function clickEvent(e: MouseEvent) {
    setMouseDown(true);
    setLastPosition({ x: e.clientX, y: e.clientY });
    if (tool == Tool.ZOOM) {
      handleZoom(e.button === 0 ? -100 : 100, e.clientX, e.clientY);
    } else if (tool == Tool.EDIT) {
      if (editTool === EditTool.SQUARE) {
        drawSquare(e.button, e.clientX, e.clientY);
      } else if (editTool === EditTool.CIRCLE) {
        // handle circle
      }
    }
  }

  function drawSquare(button: number, clientX: number, clientY: number) {
    // Calculate tile coordinates
    const x = Math.floor((clientX - position.x) / (32 * zoom));
    const y = Math.floor((clientY - position.y) / (32 * zoom));
    if (button === 1) {
      // Add new edit if left mouse button is pressed
      setEdits([...edits, { x, y, color: colors[selectedColor] }]);
    } else if (button == 2) {
      // Remove edit if right mouse button is pressed
      setEdits(edits.filter((edit) => edit.x !== x || edit.y !== y));
    }
  }

  function moveEvent(e: MouseEvent) {
    if (mouseDown) {
      if (tool == Tool.HAND || e.buttons == 4) {
        let dx = position.x + e.clientX - lastPosition.x;
        let dy = position.y + e.clientY - lastPosition.y;
        // Prevent coordinates from going out of bounds
        dx = Math.min(dx, 0);
        dx = Math.max(dx, -gridSize.width * zoom + width);
        dy = Math.min(dy, 0);
        dy = Math.max(dy, -gridSize.height * zoom + height);
        setPosition({ x: dx, y: dy });
        setLastPosition({ x: e.clientX, y: e.clientY });
      } else if (tool === Tool.EDIT) {
        if (editTool === EditTool.SQUARE) {
          drawSquare(e.buttons, e.clientX, e.clientY);
        } else if (editTool === EditTool.CIRCLE) {
          // handle circle
        }
      } else if (tool === Tool.TOKEN) {
        // handle token
      }
    }
  }

  function zoomEvent(e: WheelEvent) {
    handleZoom(e.deltaY, e.clientX, e.clientY);
  }

  function handleZoom(delta: number, clientX: number, clientY: number) {
    let newZoom = zoom;
    if (delta > 0) {
      newZoom = zoom / 1.1;
    } else {
      newZoom = zoom * 1.1;
    }
    newZoom = Math.min(newZoom, 3);
    newZoom = Math.max(newZoom, 0.6);
    console.log(newZoom);
    setZoom(newZoom);
    // Adjust position to zoom in on mouse position
    const dx = (position.x - clientX) * (newZoom / zoom) + clientX;
    const dy = (position.y - clientY) * (newZoom / zoom) + clientY;
    setPosition({ x: dx, y: dy });
  }

  return (
    <Box>
      <Stage
        width={width}
        height={height}
        options={{
          backgroundColor: 0x333333,
          antialias: false
        }}
        onMouseDown={(e) => clickEvent(e)}
        onMouseUp={() => setMouseDown(false)}
        onMouseMove={(e) => moveEvent(e)}
        onWheel={(e) => zoomEvent(e)}
      >
        <Graphics x={position.x} y={position.y} draw={drawGrid} />
        <Graphics x={position.x} y={position.y} draw={drawEdits} />
      </Stage>
      <TileControls
        tool={tool}
        setTool={setTool}
        editTool={editTool}
        setEditTool={setEditTool}
        colors={colors}
        setColors={setColors}
        selectedColor={selectedColor}
        setSelectedColor={setSelectedColor}
      />
    </Box>
  );
}
