<template>
  <div class="grid-canvas" ref="container">
    <canvas ref="canvas" :width="width" :height="height" />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';

const props = defineProps({
  masterImageUrl: { type: String, required: true },
  cellSize: { type: Number, required: true },
});

const emit = defineEmits(['selection-changed']);

const container = ref(null);
const canvas = ref(null);
let ctx = null;

const width = 1200;
const height = 800;

  let isPanning = false;
  let start = { x: 0, y: 0 };
  const offset = { x: 0, y: 0 };
  let scale = 1;
  let pinchActive = false;
  let lastDistance = 0;

  // selection in pixel coordinates relative to canvas (for drawing)
  let selection = null; // {x,y,w,h} in pixels
  let selecting = false; // whether we are drawing a selection rect

function drawGrid() {
  if (!ctx) return;
  ctx.clearRect(0, 0, width, height);

  // Draw master image background if available
  if (bgImage && bgImage.complete) {
    ctx.drawImage(bgImage, offset.x, offset.y, width * scale, height * scale);
  } else {
    ctx.fillStyle = '#f3f3f3';
    ctx.fillRect(0, 0, width, height);
  }

  // Draw grid lines
  ctx.strokeStyle = 'rgba(0,0,0,0.08)';
  const step = props.cellSize * scale;
  for (let x = offset.x % step; x < width; x += step) {
    ctx.beginPath();
    ctx.moveTo(x, 0);
    ctx.lineTo(x, height);
    ctx.stroke();
  }
  for (let y = offset.y % step; y < height; y += step) {
    ctx.beginPath();
    ctx.moveTo(0, y);
    ctx.lineTo(width, y);
    ctx.stroke();
  }

  // Draw selection (pixel coords)
  if (selection) {
    ctx.fillStyle = 'rgba(34,197,94,0.2)';
    ctx.fillRect(selection.x, selection.y, selection.w, selection.h);
    ctx.strokeStyle = 'rgba(34,197,94,0.8)';
    ctx.strokeRect(selection.x, selection.y, selection.w, selection.h);
  }
}

let bgImage = null;
watch(() => props.masterImageUrl, (v) => {
  if (!v) return;
  bgImage = new Image();
  bgImage.src = v;
  bgImage.onload = () => drawGrid();
});

onMounted(() => {
  const c = canvas.value;
  ctx = c.getContext('2d');
  drawGrid();

  c.addEventListener('pointerdown', (e) => {
    // Determine if this is a selection or a pan.
    // Desktop: hold Shift to select. Touch: treat as selection.
    const rect = c.getBoundingClientRect();
    const canvasX = e.clientX - rect.left;
    const canvasY = e.clientY - rect.top;

    if (e.pointerType === 'touch' || e.shiftKey) {
      selecting = true;
      selection = { x: canvasX, y: canvasY, w: 0, h: 0 };
      // emit initial empty selection
      emit('selection-changed', null);
    } else {
      isPanning = true;
      start = { x: e.clientX, y: e.clientY };
    }
  });

  // Touch pinch handlers (for older browsers this may be redundant with pointer events)
  c.addEventListener('touchstart', (e) => {
    if (e.touches && e.touches.length === 2) {
      pinchActive = true;
      const dx = e.touches[0].clientX - e.touches[1].clientX;
      const dy = e.touches[0].clientY - e.touches[1].clientY;
      lastDistance = Math.hypot(dx, dy);
    }
  }, { passive: false });

  c.addEventListener('touchmove', (e) => {
    if (!pinchActive || !e.touches || e.touches.length < 2) return;
    const dx = e.touches[0].clientX - e.touches[1].clientX;
    const dy = e.touches[0].clientY - e.touches[1].clientY;
    const dist = Math.hypot(dx, dy);
    if (lastDistance <= 0) {
      lastDistance = dist;
      return;
    }
    const factor = dist / lastDistance;
    const newScale = Math.min(4, Math.max(0.5, scale * factor));
    // adjust offset to keep midpoint stable
    const rect = c.getBoundingClientRect();
    const midX = (e.touches[0].clientX + e.touches[1].clientX) / 2 - rect.left;
    const midY = (e.touches[0].clientY + e.touches[1].clientY) / 2 - rect.top;

    // compute world coords of midpoint
    const worldX = (midX - offset.x) / scale;
    const worldY = (midY - offset.y) / scale;

    scale = newScale;

    // recompute offset so world point stays under midpoint
    offset.x = midX - worldX * scale;
    offset.y = midY - worldY * scale;

    lastDistance = dist;
    drawGrid();
    e.preventDefault();
  }, { passive: false });

  c.addEventListener('touchend', (e) => {
    if (!e.touches || e.touches.length < 2) {
      pinchActive = false;
      lastDistance = 0;
    }
  });

  c.addEventListener('pointermove', (e) => {
    const rect = c.getBoundingClientRect();
    const canvasX = e.clientX - rect.left;
    const canvasY = e.clientY - rect.top;

    if (selecting && selection) {
      const x = Math.min(selection.x, canvasX);
      const y = Math.min(selection.y, canvasY);
      const w = Math.abs(canvasX - selection.x);
      const h = Math.abs(canvasY - selection.y);
      selection.x = x;
      selection.y = y;
      selection.w = w;
      selection.h = h;
      drawGrid();

      // Map pixel selection to cell units and emit
      const relX = selection.x - offset.x;
      const relY = selection.y - offset.y;
      const cellSize = props.cellSize;
      const cellX = Math.max(0, Math.floor(relX / cellSize));
      const cellY = Math.max(0, Math.floor(relY / cellSize));
      const wCells = Math.max(1, Math.ceil(selection.w / cellSize));
      const hCells = Math.max(1, Math.ceil(selection.h / cellSize));

      emit('selection-changed', { x: cellX, y: cellY, w: wCells, h: hCells });
      return;
    }

    if (!isPanning) return;
    const dx = e.clientX - start.x;
    const dy = e.clientY - start.y;
    offset.x += dx;
    offset.y += dy;
    start = { x: e.clientX, y: e.clientY };
    drawGrid();
  });

  c.addEventListener('pointerup', () => {
    if (selecting && selection) {
      // finalize selection and emit one last time
      const relX = selection.x - offset.x;
      const relY = selection.y - offset.y;
      const cellSize = props.cellSize;
      const cellX = Math.max(0, Math.floor(relX / cellSize));
      const cellY = Math.max(0, Math.floor(relY / cellSize));
      const wCells = Math.max(1, Math.ceil(selection.w / cellSize));
      const hCells = Math.max(1, Math.ceil(selection.h / cellSize));

      emit('selection-changed', { x: cellX, y: cellY, w: wCells, h: hCells });
      selecting = false;
    }
    isPanning = false;
  });
});

onBeforeUnmount(() => {
  // cleanup if needed
});

// Note: This is a small scaffold: selection math and precise cell mapping
// will be expanded in future iterations. Emit selection-changed with cell units.

</script>

<style scoped>
.grid-canvas {
  width: 100%;
  height: 100%;
  background: #fff;
}
canvas {
  max-width: 100%;
  border: 1px solid rgba(0,0,0,0.06);
}
</style>
