const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

const width = 1000;
const height = 1000;

canvas.style.width = width + "px";
canvas.style.height = height + "px";
canvas.width = width;
canvas.height = height;

let minX = -2,
  minY = -2,
  maxX = 2,
  maxY = 2;

let selection = null;
let isMouseDown = false;
let mouseStartPosition = null;

let mandelbrot = ctx.createImageData(width, height);

function calcRe(col) {
  return (col * (maxX - minX)) / width + minX;
}

function calcIm(row) {
  return (row * (maxY - minY)) / height + minY;
}

function drawMandelbrotSet() {
  ctx.putImageData(mandelbrot, 0, 0);
}

let needToDraw = false;

function draw() {
  if (needToDraw) {
    ctx.clearRect(0, 0, width, height);
    drawMandelbrotSet();
  }

  if (selection) {
    ctx.fillStyle = "rgba(0, 0, 255, 0.8)";
    ctx.fillRect(
      selection.startX,
      selection.startY,
      selection.endX - selection.startX,
      selection.endY - selection.startY
    );

    needToDraw = true;
  }

  setTimeout(draw, 1000 / 60);
}

canvas.addEventListener("mousedown", (event) => {
  isMouseDown = true;
  selection = {
    startX: event.clientX - event.target.offsetLeft,
    startY: event.clientY - event.target.offsetTop,
    endX: event.clientX - event.target.offsetLeft,
    endY: event.clientY - event.target.offsetTop,
  };
});

canvas.addEventListener("mousemove", (event) => {
  if (isMouseDown) {
    const posX = event.clientX - event.target.offsetLeft;
    const posY = event.clientY - event.target.offsetTop;
    const dx = posX - selection.startX;
    const dy = posY - selection.startY;
    if (Math.abs(dx) > Math.abs(dy)) {
      selection.endX = selection.startX + dx;
      selection.endY = selection.startY + dx;
    } else {
      selection.endX = selection.startX + dy;
      selection.endY = selection.startY + dy;
    }
  }
});

canvas.addEventListener("mouseup", (event) => {
  isMouseDown = false;

  const newMinX = calcRe(selection.startX);
  const newMinY = calcIm(selection.startY);
  const newMaxX = calcRe(selection.endX);
  const newMaxY = calcIm(selection.endY);

  minX = newMinX;
  minY = newMinY;
  maxX = newMaxX;
  maxY = newMaxY;
  updateWorker();

  selection = null;
});

let worker;

function updateWorker() {
  worker.postMessage([{
    mandelbrot: mandelbrot,
    width,
    height,
    minX,
    maxX,
    minY,
    maxY,
  }]);
}

function initWorker() {
  worker = new Worker('worker.js');
  updateWorker();

  worker.onmessage = (e) => {
    mandelbrot = e.data[0];
    needToDraw = true;
  };
}

initWorker();
draw();