import * as Blockly from 'blockly';
import { getTemplate } from './robotComponents.js';

/**
 * @param {Blockly.WorkspaceSvg} workspace
 * @returns {{ x: number, y: number }}
 */
function suggestStatementStackOrigin(workspace) {
  const tops = workspace.getTopBlocks(false);
  if (!tops.length) return { x: 40, y: 40 };
  let minY = Infinity;
  for (const b of tops) {
    const xy = b.getRelativeToSurfaceXY();
    minY = Math.min(minY, xy.y);
  }
  return { x: 40, y: Math.max(24, minY - 24) };
}

/**
 * @param {Blockly.Block} block
 * @param {number} x
 * @param {number} y
 */
function moveBlockTo(block, x, y) {
  const xy = block.getRelativeToSurfaceXY();
  block.moveBy(x - xy.x, y - xy.y);
}

/**
 * @param {Blockly.WorkspaceSvg} workspace
 * @param {{ kind: string, fields: Record<string, string> }[]} components
 */
export function applyRobotToWorkspace(workspace, components) {
  Blockly.Events.setGroup(true);
  try {
    const statements = [];
    const sonarRows = [];
    for (const row of components) {
      const t = getTemplate(row.kind);
      if (!t) continue;
      if (t.applyAs === 'statement') statements.push(row);
      else if (t.applyAs === 'sonar_reporter') sonarRows.push(row);
    }

    const origin = suggestStatementStackOrigin(workspace);
    let head = /** @type {Blockly.Block | null} */ (null);
    let tail = /** @type {Blockly.Block | null} */ (null);

    for (const row of statements) {
      const t = getTemplate(row.kind);
      if (!t || t.applyAs !== 'statement') continue;
      const block = workspace.newBlock(t.blockType);
      for (const [key, val] of Object.entries(row.fields)) {
        if (block.getField(key)) {
          block.setFieldValue(String(val), key);
        }
      }
      block.initSvg();
      block.render();
      if (!head) {
        head = block;
        tail = block;
      } else if (tail && tail.nextConnection && block.previousConnection) {
        tail.nextConnection.connect(block.previousConnection);
        tail = block;
      }
    }

    if (head) {
      moveBlockTo(head, origin.x, origin.y);
    }

    let sonarX = origin.x + 280;
    let sonarY = origin.y;
    for (const row of sonarRows) {
      const t = getTemplate(row.kind);
      if (!t || t.applyAs !== 'sonar_reporter') continue;
      const main = workspace.newBlock(t.blockType);
      const trig = workspace.newBlock('math_number');
      const echo = workspace.newBlock('math_number');
      trig.setFieldValue(String(row.fields.TRIG ?? '5'), 'NUM');
      echo.setFieldValue(String(row.fields.ECHO ?? '18'), 'NUM');
      trig.initSvg();
      trig.render();
      echo.initSvg();
      echo.render();
      main.initSvg();
      main.render();
      const trigIn = main.getInput('TRIG');
      const echoIn = main.getInput('ECHO');
      if (trigIn?.connection && trig.outputConnection) {
        trigIn.connection.connect(trig.outputConnection);
      }
      if (echoIn?.connection && echo.outputConnection) {
        echoIn.connection.connect(echo.outputConnection);
      }
      moveBlockTo(main, sonarX, sonarY);
      sonarY += 56;
    }
  } finally {
    Blockly.Events.setGroup(false);
  }

}
