// =============================================================================
// Constants
// =============================================================================

const CANVAS_W = 1920;
const CANVAS_H = 1080;
const ZOOM_MIN = 0.1;
const ZOOM_MAX = 5;
const ZOOM_IN_FACTOR = 1.1;
const ZOOM_OUT_FACTOR = 0.9;
const PDF_ZOOM_STEP = 1.1;
const PDF_MIN_SCALE = 0.05;
const SNAP_SEARCH_RADIUS = 20;
const ROTATION_STEP = 15;
const CONVEYOR_MIN_W = 40;

const PRIORITY_TYPES = new Set([
  'conveyor', 'conveyor_v', 'chute', 'chute_v',
  'tipper', 'tipper_v', 'extendo', 'extendo_v',
  'induction', 'induction_v',
]);

const SYMBOLS = [
  { id: 'conveyor',   name: 'Conveyor',        file: 'symbols/conveyor_no_comm.svg', w: 154, h: 30 },
  { id: 'conveyor_v', name: 'Conveyor (V)',     file: 'symbols/conveyor_no_comm.svg', w: 154, h: 30, defaultRotation: 90 },
  { id: 'chute',      name: 'Chute',            file: 'symbols/chute_no_comm.svg',    w: 68,  h: 20 },
  { id: 'chute_v',    name: 'Chute (V)',        file: 'symbols/chute_no_comm.svg',    w: 68,  h: 20, defaultRotation: 90 },
  { id: 'tipper',     name: 'Tipper',           file: 'symbols/tipper_no_comm.svg',   w: 68,  h: 20 },
  { id: 'tipper_v',   name: 'Tipper (V)',       file: 'symbols/tipper_no_comm.svg',   w: 68,  h: 20, defaultRotation: 90 },
  { id: 'extendo',    name: 'Extendo',          file: 'symbols/extendo_no_comm.svg',  w: 73,  h: 20 },
  { id: 'extendo_v',  name: 'Extendo (V)',      file: 'symbols/extendo_no_comm.svg',  w: 73,  h: 20, defaultRotation: 90 },
  { id: 'induction',  name: 'Induction',        file: 'symbols/induction_no_comm.svg',w: 42,  h: 20 },
  { id: 'induction_v',name: 'Induction (V)',    file: 'symbols/induction_no_comm.svg',w: 42,  h: 20, defaultRotation: 90 },
  { id: 'pmm',        name: 'PMM',              file: 'symbols/pmm_no_comm.svg',      w: 49,  h: 20 },
  { id: 'dpm',        name: 'DPM',              file: 'symbols/dpm_no_comm.svg',      w: 35,  h: 20 },
  { id: 'fio_sio_fioh', name: 'FIO/SIO/FIOH',  file: 'symbols/fio_sio_fioh_no_comm.svg', w: 14, h: 20 },
  { id: 'pressure_sensor', name: 'Pressure Sensor', file: 'symbols/pressure_sensor_no_comm.svg', w: 20, h: 20 },
  { id: 'epc',        name: 'EPC',              file: 'symbols/epc_no_comm.svg',      w: 84,  h: 20 },
  { id: 'photoeye',   name: 'Photoeye',         file: 'symbols/photoeye_no_comm.svg', w: 56,  h: 20 },
  { id: 'ip_camera',  name: 'IP Camera',        file: 'symbols/ip_camera.svg',        w: 20,  h: 20 },
  { id: 'mcm',        name: 'MCM',              file: 'symbols/mcm_no_comm.svg',      w: 60,  h: 20 },
  { id: 'diverter',   name: 'Diverter',         file: 'symbols/diverter_no_comm.svg', w: 31,  h: 20 },
  { id: 'jam_reset',  name: 'Jam Reset (JR)',   file: 'symbols/jam_reset_no_comm.svg',w: 20,  h: 20 },
  { id: 'start',      name: 'Start (S)',        file: 'symbols/start_no_comm.svg',    w: 20,  h: 20 },
  { id: 'chute_enable', name: 'Chute Enable',   file: 'symbols/chute_enable_no_comm.svg', w: 20, h: 20 },
  { id: 'package_release', name: 'Package Release', file: 'symbols/package_release_no_comm.svg', w: 20, h: 20 },
  { id: 'start_stop', name: 'Start Stop (SS)',  file: 'symbols/start_stop_no_comm.svg', w: 40, h: 20 },
];

// =============================================================================
// Cached DOM References
// =============================================================================

const dom = {
  gridSize: document.getElementById('gridSize'),
  minSpacing: document.getElementById('minSpacing'),
  snapEnabled: document.getElementById('snapEnabled'),
  showGrid: document.getElementById('showGrid'),
  gridOverlay: document.getElementById('grid-overlay'),
  dropZone: document.getElementById('drop-zone'),
  palette: document.getElementById('palette'),
  canvas: document.getElementById('canvas'),
  canvasWrapper: document.getElementById('canvas-wrapper'),
  pdfBackground: document.getElementById('pdf-background'),
  pdfInfo: document.getElementById('pdfInfo'),
  editBackgroundBtn: document.getElementById('editBackground'),
  importFile: document.getElementById('importFile'),
  pdfFile: document.getElementById('pdfFile'),
};

// =============================================================================
// MCM State Management
// =============================================================================

let currentMcm = document.getElementById('mcmSelect').value;

function getMcmStorageKey(mcm) {
  return 'scada_mcm_' + mcm;
}

function saveMcmState() {
  const state = {
    symbols: placedSymbols.map(({ symbolId, name, file, x, y, w, h, rotation }) => (
      { symbolId, name, file, x, y, w, h, rotation: rotation || 0 }
    )),
    nextId,
    gridSize: getGridSize(),
    minSpacing: getMinSpacing(),
    pdfScale,
    pdfOffsetX,
    pdfOffsetY,
  };
  localStorage.setItem(getMcmStorageKey(currentMcm), JSON.stringify(state));
}

function loadMcmState(mcm) {
  const raw = localStorage.getItem(getMcmStorageKey(mcm));
  if (!raw) {
    placedSymbols = [];
    nextId = 1;
    selectedId = null;
    renderPlacedSymbols();
    return;
  }
  try {
    const state = JSON.parse(raw);
    placedSymbols = [];
    nextId = 1;
    selectedId = null;
    if (state.gridSize) dom.gridSize.value = state.gridSize;
    if (state.minSpacing) dom.minSpacing.value = state.minSpacing;
    if (state.pdfScale) pdfScale = state.pdfScale;
    if (state.pdfOffsetX !== undefined) pdfOffsetX = state.pdfOffsetX;
    if (state.pdfOffsetY !== undefined) pdfOffsetY = state.pdfOffsetY;
    for (const s of (state.symbols || [])) {
      placedSymbols.push({
        id: nextId++, symbolId: s.symbolId, name: s.name,
        file: s.file, x: s.x, y: s.y, w: s.w, h: s.h,
        rotation: s.rotation || 0,
      });
    }
    if (state.nextId && state.nextId > nextId) nextId = state.nextId;
    drawGrid();
    renderPlacedSymbols();
    if (pdfPage) renderPDFBackground();
  } catch (e) {
    console.error('Failed to load MCM state:', e);
  }
}

// =============================================================================
// Application State
// =============================================================================

let placedSymbols = [];
let nextId = 1;
let selectedId = null;
let dragState = null;

// Zoom / Pan
let zoomLevel = 1;
let panX = 0;
let panY = 0;
let isPanning = false;
let panStartX = 0;
let panStartY = 0;

// PDF Background
let pdfScale = 1.0;
let pdfPage = null;
let pdfNatWidth = 0;
let pdfNatHeight = 0;
let pdfOffsetX = 0;
let pdfOffsetY = 0;
let editingBackground = false;
let pdfDragState = null;

// =============================================================================
// Settings Helpers
// =============================================================================

function getGridSize() { return parseInt(dom.gridSize.value) || 20; }
function getMinSpacing() { return parseInt(dom.minSpacing.value) || 10; }
function isSnapEnabled() { return dom.snapEnabled.checked; }

// =============================================================================
// Utilities
// =============================================================================

function clamp(value, min, max) {
  return Math.max(min, Math.min(max, value));
}

function downloadBlob(blob, filename) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

function createSvgElement(tag, attrs) {
  const el = document.createElementNS('http://www.w3.org/2000/svg', tag);
  for (const [key, val] of Object.entries(attrs)) {
    el.setAttribute(key, val);
  }
  return el;
}

// =============================================================================
// Coordinate Transforms
// =============================================================================

function applyTransform() {
  dom.canvas.style.transform = `translate(${panX}px, ${panY}px) scale(${zoomLevel})`;
}

function screenToCanvas(clientX, clientY) {
  const rect = dom.canvasWrapper.getBoundingClientRect();
  return {
    x: (clientX - rect.left - panX) / zoomLevel,
    y: (clientY - rect.top - panY) / zoomLevel,
  };
}

function snapToGrid(x, y) {
  if (!isSnapEnabled()) return { x, y };
  const size = getGridSize();
  return {
    x: Math.round(x / size) * size,
    y: Math.round(y / size) * size,
  };
}

// =============================================================================
// Grid Rendering
// =============================================================================

function drawGrid() {
  const svg = dom.gridOverlay;
  const size = getGridSize();
  svg.innerHTML = '';

  if (!dom.showGrid.checked) return;

  const defs = createSvgElement('defs', {});
  const pattern = createSvgElement('pattern', {
    id: 'gridPattern', width: size, height: size, patternUnits: 'userSpaceOnUse',
  });
  pattern.appendChild(createSvgElement('line', {
    x1: 0, y1: 0, x2: size, y2: 0, stroke: '#333', 'stroke-width': '0.5',
  }));
  pattern.appendChild(createSvgElement('line', {
    x1: 0, y1: 0, x2: 0, y2: size, stroke: '#333', 'stroke-width': '0.5',
  }));
  defs.appendChild(pattern);
  svg.appendChild(defs);
  svg.appendChild(createSvgElement('rect', {
    width: CANVAS_W, height: CANVAS_H, fill: 'url(#gridPattern)',
  }));
}

// =============================================================================
// Rotation-Aware Bounding Box
// =============================================================================

function getAABB(x, y, w, h, rotation) {
  if (!rotation) return { x, y, w, h };
  const cx = x + w / 2;
  const cy = y + h / 2;
  const rad = rotation * Math.PI / 180;
  const cos = Math.abs(Math.cos(rad));
  const sin = Math.abs(Math.sin(rad));
  const bw = w * cos + h * sin;
  const bh = w * sin + h * cos;
  return { x: cx - bw / 2, y: cy - bh / 2, w: bw, h: bh };
}

// =============================================================================
// Spacing & Collision
// =============================================================================

function edgeDistance(ax, ay, aw, ah, bx, by, bw, bh) {
  const dx = Math.max(0, Math.max(ax - (bx + bw), bx - (ax + aw)));
  const dy = Math.max(0, Math.max(ay - (by + bh), by - (ay + ah)));

  if (dx === 0 && dy === 0) return 0;
  if (dx === 0) return dy;
  if (dy === 0) return dx;
  return Math.sqrt(dx * dx + dy * dy);
}

function checkSpacingViolation(id, x, y, w, h, rotation) {
  const spacing = getMinSpacing();
  const a = getAABB(x, y, w, h, rotation);
  for (const sym of placedSymbols) {
    if (sym.id === id) continue;
    const b = getAABB(sym.x, sym.y, sym.w, sym.h, sym.rotation);
    if (edgeDistance(a.x, a.y, a.w, a.h, b.x, b.y, b.w, b.h) < spacing) return true;
  }
  return false;
}

function findValidPosition(id, x, y, w, h, symbolId, rotation) {
  const snapped = snapToGrid(x, y);
  let sx = snapped.x, sy = snapped.y;

  if (symbolId && PRIORITY_TYPES.has(symbolId)) return { x: sx, y: sy };
  if (!checkSpacingViolation(id, sx, sy, w, h, rotation)) return { x: sx, y: sy };

  const step = isSnapEnabled() ? getGridSize() : 1;
  for (let r = 1; r <= SNAP_SEARCH_RADIUS; r++) {
    for (let dx = -r; dx <= r; dx++) {
      for (let dy = -r; dy <= r; dy++) {
        if (Math.abs(dx) !== r && Math.abs(dy) !== r) continue;
        const cx = sx + dx * step;
        const cy = sy + dy * step;
        const bb = getAABB(cx, cy, w, h, rotation);
        if (bb.x < 0 || bb.y < 0 || bb.x + bb.w > CANVAS_W || bb.y + bb.h > CANVAS_H) continue;
        if (!checkSpacingViolation(id, cx, cy, w, h, rotation)) return { x: cx, y: cy };
      }
    }
  }
  return { x: sx, y: sy };
}

// =============================================================================
// Context Menu
// =============================================================================

function removeContextMenu() {
  document.querySelectorAll('.context-menu').forEach(m => m.remove());
}

function showContextMenu(x, y, symId) {
  removeContextMenu();
  const menu = document.createElement('div');
  menu.className = 'context-menu';
  menu.style.left = x + 'px';
  menu.style.top = y + 'px';

  const actions = [
    { label: 'Delete', fn: () => {
      placedSymbols = placedSymbols.filter(s => s.id !== symId);
      if (selectedId === symId) selectedId = null;
      renderPlacedSymbols();
    }},
    { label: 'Duplicate', fn: () => {
      const orig = placedSymbols.find(s => s.id === symId);
      if (!orig) return;
      const pos = findValidPosition(-1, orig.x + 20, orig.y + 20, orig.w, orig.h, orig.symbolId, orig.rotation);
      placedSymbols.push({
        id: nextId++, symbolId: orig.symbolId, file: orig.file,
        name: orig.name, x: pos.x, y: pos.y, w: orig.w, h: orig.h,
        rotation: orig.rotation || 0,
      });
      renderPlacedSymbols();
    }},
  ];

  for (const action of actions) {
    const item = document.createElement('div');
    item.className = 'context-menu-item';
    item.textContent = action.label;
    item.addEventListener('click', () => { action.fn(); removeContextMenu(); });
    menu.appendChild(item);
  }
  document.body.appendChild(menu);
}

// =============================================================================
// Render Placed Symbols
// =============================================================================

function isConveyorType(symbolId) {
  return symbolId === 'conveyor' || symbolId === 'conveyor_v';
}

function renderPlacedSymbols() {
  dom.dropZone.innerHTML = '';
  saveMcmState();

  for (const sym of placedSymbols) {
    const div = document.createElement('div');
    div.className = 'placed-symbol';
    if (sym.id === selectedId) div.classList.add('selected');
    div.dataset.id = sym.id;
    Object.assign(div.style, {
      left: sym.x + 'px', top: sym.y + 'px',
      width: sym.w + 'px', height: sym.h + 'px',
    });

    if (sym.rotation) {
      div.style.transform = `rotate(${sym.rotation}deg)`;
      div.style.transformOrigin = 'center center';
    }

    const img = document.createElement('img');
    img.src = sym.file;
    img.draggable = false;
    div.appendChild(img);

    // Resize handle for conveyors
    if (isConveyorType(sym.symbolId) && sym.id === selectedId) {
      const handle = document.createElement('div');
      handle.className = 'resize-handle';
      handle.addEventListener('mousedown', (e) => {
        if (e.button !== 0) return;
        e.stopPropagation();
        e.preventDefault();
        const pos = screenToCanvas(e.clientX, e.clientY);
        dragState = {
          type: 'resize', placedId: sym.id,
          startX: pos.x, startY: pos.y, origW: sym.w,
        };
      });
      div.appendChild(handle);
    }

    div.addEventListener('mousedown', (e) => {
      if (e.button !== 0) return;
      e.stopPropagation();
      e.preventDefault();
      selectedId = sym.id;
      const pos = screenToCanvas(e.clientX, e.clientY);
      dragState = {
        type: 'move', placedId: sym.id,
        offsetX: pos.x - sym.x, offsetY: pos.y - sym.y,
      };
      div.classList.add('dragging');
      renderPlacedSymbols();
    });

    div.addEventListener('contextmenu', (e) => {
      e.preventDefault();
      e.stopPropagation();
      showContextMenu(e.clientX, e.clientY, sym.id);
    });

    dom.dropZone.appendChild(div);
  }
}

// =============================================================================
// Palette
// =============================================================================

function buildPalette() {
  dom.palette.innerHTML = '';

  for (const sym of SYMBOLS) {
    const item = document.createElement('div');
    item.className = 'palette-item';
    item.dataset.symbolId = sym.id;

    const img = document.createElement('img');
    img.src = sym.file;
    img.draggable = false;
    if (sym.defaultRotation) {
      img.style.transform = `rotate(${sym.defaultRotation}deg)`;
    }
    item.appendChild(img);

    const label = document.createElement('span');
    label.textContent = sym.name;
    item.appendChild(label);

    item.addEventListener('mousedown', (e) => {
      if (e.button !== 0) return;
      e.preventDefault();

      const ghost = document.createElement('div');
      ghost.className = 'drag-ghost';
      ghost.style.width = sym.w + 'px';
      ghost.style.height = sym.h + 'px';
      const ghostImg = document.createElement('img');
      ghostImg.src = sym.file;
      ghostImg.style.width = '100%';
      ghostImg.style.height = '100%';
      if (sym.defaultRotation) {
        ghost.style.transform = `rotate(${sym.defaultRotation}deg)`;
      }
      ghost.appendChild(ghostImg);
      ghost.style.left = (e.clientX - sym.w / 2) + 'px';
      ghost.style.top = (e.clientY - sym.h / 2) + 'px';
      document.body.appendChild(ghost);

      dragState = { type: 'palette', symbolDef: sym, ghost };
    });

    dom.palette.appendChild(item);
  }
}

// =============================================================================
// Consolidated Mouse Handlers
// =============================================================================

document.addEventListener('mousemove', (e) => {
  // --- Pan ---
  if (isPanning) {
    panX = e.clientX - panStartX;
    panY = e.clientY - panStartY;
    applyTransform();
    return;
  }

  // --- PDF drag ---
  if (pdfDragState && editingBackground) {
    const pos = screenToCanvas(e.clientX, e.clientY);
    pdfOffsetX = pdfDragState.origOffsetX + (pos.x - pdfDragState.startX);
    pdfOffsetY = pdfDragState.origOffsetY + (pos.y - pdfDragState.startY);
    const pdfCanvas = dom.pdfBackground.querySelector('canvas');
    if (pdfCanvas) {
      pdfCanvas.style.left = pdfOffsetX + 'px';
      pdfCanvas.style.top = pdfOffsetY + 'px';
    }
    dom.pdfInfo.textContent =
      `PDF: pos: ${Math.round(pdfOffsetX)},${Math.round(pdfOffsetY)} (${Math.round(pdfScale * 100)}%)`;
    return;
  }

  // --- Symbol drag ---
  if (!dragState) return;

  if (dragState.type === 'palette') {
    const sym = dragState.symbolDef;
    dragState.ghost.style.left = (e.clientX - sym.w / 2) + 'px';
    dragState.ghost.style.top = (e.clientY - sym.h / 2) + 'px';
  }

  if (dragState.type === 'move') {
    const sym = placedSymbols.find(s => s.id === dragState.placedId);
    if (!sym) return;

    const pos = screenToCanvas(e.clientX, e.clientY);
    const bb = getAABB(0, 0, sym.w, sym.h, sym.rotation);
    const newX = clamp(pos.x - dragState.offsetX, -bb.x, CANVAS_W - bb.w - bb.x);
    const newY = clamp(pos.y - dragState.offsetY, -bb.y, CANVAS_H - bb.h - bb.y);
    const snapped = snapToGrid(newX, newY);
    sym.x = snapped.x;
    sym.y = snapped.y;

    renderPlacedSymbols();

    const el = dom.dropZone.querySelector(`[data-id="${sym.id}"]`);
    if (el && checkSpacingViolation(sym.id, sym.x, sym.y, sym.w, sym.h, sym.rotation)) {
      el.classList.add('collision');
    }
  }

  if (dragState.type === 'resize') {
    const sym = placedSymbols.find(s => s.id === dragState.placedId);
    if (!sym) return;

    const pos = screenToCanvas(e.clientX, e.clientY);
    const dx = pos.x - dragState.startX;
    const dy = pos.y - dragState.startY;
    const rad = (sym.rotation || 0) * Math.PI / 180;
    const projectedDelta = dx * Math.cos(rad) + dy * Math.sin(rad);
    let newW = dragState.origW + projectedDelta;
    if (isSnapEnabled()) {
      newW = Math.round(newW / getGridSize()) * getGridSize();
    }
    sym.w = Math.max(CONVEYOR_MIN_W, newW);
    renderPlacedSymbols();
  }
});

document.addEventListener('mouseup', (e) => {
  // --- Pan end ---
  if (e.button === 1 && isPanning) {
    isPanning = false;
    document.body.style.cursor = '';
    return;
  }

  // --- PDF drag end ---
  if (pdfDragState) {
    pdfDragState = null;
    saveMcmState();
    return;
  }

  // --- Symbol drag end ---
  if (!dragState) return;

  if (dragState.type === 'palette') {
    dragState.ghost.remove();
    const sym = dragState.symbolDef;
    const rot = sym.defaultRotation || 0;
    const pos = screenToCanvas(e.clientX, e.clientY);
    let dropX = pos.x - sym.w / 2;
    let dropY = pos.y - sym.h / 2;

    if (dropX >= -sym.w && dropX <= CANVAS_W && dropY >= -sym.h && dropY <= CANVAS_H) {
      dropX = clamp(dropX, 0, CANVAS_W - sym.w);
      dropY = clamp(dropY, 0, CANVAS_H - sym.h);
      const valid = findValidPosition(-1, dropX, dropY, sym.w, sym.h, sym.id, rot);
      placedSymbols.push({
        id: nextId++, symbolId: sym.id, file: sym.file,
        name: sym.name, x: valid.x, y: valid.y, w: sym.w, h: sym.h,
        rotation: rot,
      });
      renderPlacedSymbols();
    }
  }

  if (dragState.type === 'move') {
    const sym = placedSymbols.find(s => s.id === dragState.placedId);
    if (sym) {
      const valid = findValidPosition(sym.id, sym.x, sym.y, sym.w, sym.h, sym.symbolId, sym.rotation);
      sym.x = valid.x;
      sym.y = valid.y;
    }
    renderPlacedSymbols();
  }

  if (dragState.type === 'resize') {
    renderPlacedSymbols();
  }

  dragState = null;
});

// =============================================================================
// Canvas Interactions
// =============================================================================

dom.dropZone.addEventListener('mousedown', (e) => {
  if (e.target === e.currentTarget) {
    selectedId = null;
    renderPlacedSymbols();
    removeContextMenu();
  }
});

document.addEventListener('click', removeContextMenu);

document.addEventListener('keydown', (e) => {
  if (e.key === 'Delete' && selectedId !== null) {
    placedSymbols = placedSymbols.filter(s => s.id !== selectedId);
    selectedId = null;
    renderPlacedSymbols();
  }

  // Rotation: E = clockwise, Q = counter-clockwise
  if (selectedId !== null && (e.key === 'e' || e.key === 'E')) {
    const sym = placedSymbols.find(s => s.id === selectedId);
    if (sym) {
      sym.rotation = ((sym.rotation || 0) + ROTATION_STEP) % 360;
      renderPlacedSymbols();
    }
  }
  if (selectedId !== null && (e.key === 'q' || e.key === 'Q')) {
    const sym = placedSymbols.find(s => s.id === selectedId);
    if (sym) {
      sym.rotation = ((sym.rotation || 0) - ROTATION_STEP + 360) % 360;
      renderPlacedSymbols();
    }
  }
});

// =============================================================================
// Zoom & Pan
// =============================================================================

let pdfReRenderTimer = null;

function schedulePdfReRender() {
  if (!pdfPage) return;
  clearTimeout(pdfReRenderTimer);
  pdfReRenderTimer = setTimeout(() => renderPDFBackground(), 150);
}

dom.canvasWrapper.addEventListener('wheel', (e) => {
  e.preventDefault();
  const rect = dom.canvasWrapper.getBoundingClientRect();
  const mx = e.clientX - rect.left;
  const my = e.clientY - rect.top;
  const cx = (mx - panX) / zoomLevel;
  const cy = (my - panY) / zoomLevel;

  const factor = e.deltaY > 0 ? ZOOM_OUT_FACTOR : ZOOM_IN_FACTOR;
  zoomLevel = clamp(zoomLevel * factor, ZOOM_MIN, ZOOM_MAX);

  panX = mx - cx * zoomLevel;
  panY = my - cy * zoomLevel;
  applyTransform();
  schedulePdfReRender();
}, { passive: false });

dom.canvasWrapper.addEventListener('mousedown', (e) => {
  if (e.button === 1) {
    e.preventDefault();
    isPanning = true;
    panStartX = e.clientX - panX;
    panStartY = e.clientY - panY;
    document.body.style.cursor = 'grabbing';
  }
});

// =============================================================================
// Settings
// =============================================================================

dom.gridSize.addEventListener('change', () => { drawGrid(); saveMcmState(); });
dom.showGrid.addEventListener('change', drawGrid);
dom.minSpacing.addEventListener('change', () => saveMcmState());

document.getElementById('mcmSelect').addEventListener('change', (e) => {
  saveMcmState();
  currentMcm = e.target.value;
  loadMcmState(currentMcm);
});

document.getElementById('clearCanvas').addEventListener('click', () => {
  if (!confirm('Clear all placed symbols?')) return;
  placedSymbols = [];
  selectedId = null;
  renderPlacedSymbols();
});

// =============================================================================
// Export SVG
// =============================================================================

document.getElementById('exportSVG').addEventListener('click', async () => {
  const lines = [
    '<?xml version="1.0" encoding="UTF-8" standalone="no"?>',
    `<svg width="${CANVAS_W}" height="${CANVAS_H}" viewBox="0 0 ${CANVAS_W} ${CANVAS_H}" version="1.1"`,
    '  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">',
    `  <rect width="${CANVAS_W}" height="${CANVAS_H}" fill="#1e1e1e" />`,
  ];

  for (const sym of placedSymbols) {
    try {
      const svgText = await (await fetch(sym.file)).text();
      const doc = new DOMParser().parseFromString(svgText, 'image/svg+xml');
      const svgEl = doc.documentElement;
      const viewBox = svgEl.getAttribute('viewBox') || `0 0 ${sym.w} ${sym.h}`;
      const rot = sym.rotation || 0;
      const cx = sym.x + sym.w / 2;
      const cy = sym.y + sym.h / 2;
      const rotAttr = rot ? ` transform="rotate(${rot},${cx},${cy})"` : '';
      lines.push(`  <!-- ${sym.name} -->`);
      lines.push(`  <svg x="${sym.x}" y="${sym.y}" width="${sym.w}" height="${sym.h}" viewBox="${viewBox}"${rotAttr}>`);
      lines.push(`    ${svgEl.innerHTML}`);
      lines.push('  </svg>');
    } catch (err) {
      console.error('Failed to embed symbol:', sym.name, err);
    }
  }

  lines.push('</svg>');
  downloadBlob(new Blob([lines.join('\n')], { type: 'image/svg+xml' }), 'scada_layout.svg');
});

// =============================================================================
// Save / Load Layout (JSON)
// =============================================================================

document.getElementById('saveLayout').addEventListener('click', () => {
  const data = {
    gridSize: getGridSize(),
    minSpacing: getMinSpacing(),
    symbols: placedSymbols.map(({ symbolId, name, file, x, y, w, h, rotation }) => (
      { symbolId, name, file, x, y, w, h, rotation: rotation || 0 }
    )),
  };
  downloadBlob(new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }), 'scada_layout.json');
});

document.getElementById('loadLayout').addEventListener('click', () => dom.importFile.click());

dom.importFile.addEventListener('change', (e) => {
  const file = e.target.files[0];
  if (!file) return;
  const reader = new FileReader();
  reader.onload = (ev) => {
    try {
      const data = JSON.parse(ev.target.result);
      if (data.gridSize) dom.gridSize.value = data.gridSize;
      if (data.minSpacing) dom.minSpacing.value = data.minSpacing;
      placedSymbols = [];
      nextId = 1;
      for (const s of data.symbols) {
        placedSymbols.push({
          id: nextId++, symbolId: s.symbolId, name: s.name,
          file: s.file, x: s.x, y: s.y, w: s.w, h: s.h,
          rotation: s.rotation || 0,
        });
      }
      drawGrid();
      renderPlacedSymbols();
    } catch (err) {
      alert('Invalid layout file: ' + err.message);
    }
  };
  reader.readAsText(file);
  e.target.value = '';
});

// =============================================================================
// PDF Background
// =============================================================================

let pdfRenderTask = null;

function renderPDFBackground() {
  dom.pdfBackground.innerHTML = '';
  if (!pdfPage) {
    dom.pdfInfo.textContent = '';
    return;
  }

  if (pdfRenderTask) {
    pdfRenderTask.cancel();
    pdfRenderTask = null;
  }

  const dpr = window.devicePixelRatio || 1;
  const hiResScale = pdfScale * zoomLevel * dpr;
  const viewport = pdfPage.getViewport({ scale: hiResScale });
  const displayViewport = pdfPage.getViewport({ scale: pdfScale });

  const canvas = document.createElement('canvas');
  canvas.width = viewport.width;
  canvas.height = viewport.height;
  canvas.style.width = displayViewport.width + 'px';
  canvas.style.height = displayViewport.height + 'px';
  canvas.style.left = pdfOffsetX + 'px';
  canvas.style.top = pdfOffsetY + 'px';

  pdfRenderTask = pdfPage.render({ canvasContext: canvas.getContext('2d'), viewport });
  pdfRenderTask.promise.then(() => {
    pdfRenderTask = null;
  }).catch(() => {
    pdfRenderTask = null;
  });

  dom.pdfBackground.appendChild(canvas);

  dom.pdfInfo.textContent =
    `PDF: ${Math.round(displayViewport.width)}x${Math.round(displayViewport.height)} (${Math.round(pdfScale * 100)}%) pos: ${Math.round(pdfOffsetX)},${Math.round(pdfOffsetY)}`;
}

function setEditBackgroundMode(active) {
  editingBackground = active;
  if (active) {
    dom.editBackgroundBtn.classList.add('edit-bg-active');
    dom.editBackgroundBtn.textContent = 'Done Editing';
    dom.pdfBackground.classList.add('editing');
    dom.pdfBackground.style.pointerEvents = 'auto';
    dom.pdfBackground.style.zIndex = '3';
    dom.dropZone.style.pointerEvents = 'none';
  } else {
    dom.editBackgroundBtn.classList.remove('edit-bg-active');
    dom.editBackgroundBtn.textContent = 'Edit Background';
    dom.pdfBackground.classList.remove('editing');
    dom.pdfBackground.style.pointerEvents = 'none';
    dom.pdfBackground.style.zIndex = '0';
    dom.dropZone.style.pointerEvents = 'auto';
    pdfDragState = null;
  }
}

dom.editBackgroundBtn.addEventListener('click', () => {
  if (pdfPage) setEditBackgroundMode(!editingBackground);
});

dom.pdfBackground.addEventListener('mousedown', (e) => {
  if (!editingBackground || e.button !== 0) return;
  e.preventDefault();
  e.stopPropagation();
  const pos = screenToCanvas(e.clientX, e.clientY);
  pdfDragState = {
    startX: pos.x, startY: pos.y,
    origOffsetX: pdfOffsetX, origOffsetY: pdfOffsetY,
  };
});

document.getElementById('loadPDF').addEventListener('click', () => dom.pdfFile.click());

dom.pdfFile.addEventListener('change', async (e) => {
  const file = e.target.files[0];
  if (!file) return;
  const pdf = await pdfjsLib.getDocument({ data: await file.arrayBuffer() }).promise;
  pdfPage = await pdf.getPage(1);
  const vp = pdfPage.getViewport({ scale: 1 });
  pdfNatWidth = vp.width;
  pdfNatHeight = vp.height;
  pdfScale = Math.min(CANVAS_W / pdfNatWidth, CANVAS_H / pdfNatHeight);
  renderPDFBackground();
  e.target.value = '';
});

document.getElementById('pdfZoomIn').addEventListener('click', () => {
  if (!pdfPage) return;
  pdfScale *= PDF_ZOOM_STEP;
  renderPDFBackground();
  saveMcmState();
});

document.getElementById('pdfZoomOut').addEventListener('click', () => {
  if (!pdfPage) return;
  pdfScale = Math.max(PDF_MIN_SCALE, pdfScale / PDF_ZOOM_STEP);
  renderPDFBackground();
  saveMcmState();
});

document.getElementById('pdfRemove').addEventListener('click', () => {
  pdfPage = null;
  pdfScale = 1.0;
  pdfOffsetX = 0;
  pdfOffsetY = 0;
  setEditBackgroundMode(false);
  renderPDFBackground();
});

// =============================================================================
// Init
// =============================================================================

buildPalette();
loadMcmState(currentMcm);
drawGrid();
renderPlacedSymbols();
applyTransform();
