/**
 * EAGLE .lbr Generator
 *
 * Converts KiCad .kicad_sym symbol data to EAGLE XML format (.lbr)
 * for Fusion 360 Electronics delivery.
 *
 * Coordinate mapping: Both use mm with Y-up, so it's a direct mapping.
 */

// KiCad pin type → EAGLE direction
const PIN_TYPE_MAP = {
  power_in: 'pwr',
  power_out: 'out',
  input: 'in',
  output: 'out',
  bidirectional: 'io',
  passive: 'pas',
  unconnected: 'nc',
  tri_state: 'hiz',
  unspecified: 'io',
  open_collector: 'oc',
  open_emitter: 'oc',
  free: 'io',
};

// KiCad angle → EAGLE rotation
const ANGLE_MAP = {
  0: '',              // extends right (left-side pin)
  180: ' rot="R180"', // extends left (right-side pin)
  90: ' rot="R90"',   // extends up (bottom-side pin)
  270: ' rot="R270"', // extends down (top-side pin)
};

// KiCad pin length → EAGLE length keyword
function pinLengthKeyword(len) {
  if (len <= 0) return 'point';
  if (len <= 2.54) return 'short';
  if (len <= 5.08) return 'middle';
  return 'long';
}

// Escape XML special characters
function escXml(s) {
  if (!s) return '';
  return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&apos;');
}

// Standard EAGLE layer definitions (required in every .lbr)
const LAYERS_XML = `<layers>
<layer number="1" name="Top" color="4" fill="1" visible="yes" active="yes"/>
<layer number="16" name="Bottom" color="1" fill="1" visible="yes" active="yes"/>
<layer number="17" name="Pads" color="2" fill="1" visible="yes" active="yes"/>
<layer number="18" name="Vias" color="2" fill="1" visible="yes" active="yes"/>
<layer number="19" name="Unrouted" color="6" fill="1" visible="yes" active="yes"/>
<layer number="20" name="Dimension" color="15" fill="1" visible="yes" active="yes"/>
<layer number="21" name="tPlace" color="7" fill="1" visible="yes" active="yes"/>
<layer number="22" name="bPlace" color="7" fill="1" visible="yes" active="yes"/>
<layer number="23" name="tOrigins" color="15" fill="1" visible="yes" active="yes"/>
<layer number="24" name="bOrigins" color="15" fill="1" visible="yes" active="yes"/>
<layer number="25" name="tNames" color="7" fill="1" visible="yes" active="yes"/>
<layer number="26" name="bNames" color="7" fill="1" visible="yes" active="yes"/>
<layer number="27" name="tValues" color="7" fill="1" visible="yes" active="yes"/>
<layer number="28" name="bValues" color="7" fill="1" visible="yes" active="yes"/>
<layer number="29" name="tStop" color="7" fill="3" visible="no" active="yes"/>
<layer number="30" name="bStop" color="7" fill="6" visible="no" active="yes"/>
<layer number="31" name="tCream" color="7" fill="4" visible="no" active="yes"/>
<layer number="32" name="bCream" color="7" fill="5" visible="no" active="yes"/>
<layer number="33" name="tFinish" color="6" fill="3" visible="no" active="yes"/>
<layer number="34" name="bFinish" color="6" fill="6" visible="no" active="yes"/>
<layer number="35" name="tGlue" color="7" fill="4" visible="no" active="yes"/>
<layer number="36" name="bGlue" color="7" fill="5" visible="no" active="yes"/>
<layer number="37" name="tTest" color="7" fill="1" visible="no" active="yes"/>
<layer number="38" name="bTest" color="7" fill="1" visible="no" active="yes"/>
<layer number="39" name="tKeepout" color="4" fill="11" visible="no" active="yes"/>
<layer number="40" name="bKeepout" color="1" fill="11" visible="no" active="yes"/>
<layer number="41" name="tRestrict" color="4" fill="10" visible="no" active="yes"/>
<layer number="42" name="bRestrict" color="1" fill="10" visible="no" active="yes"/>
<layer number="43" name="vRestrict" color="2" fill="10" visible="no" active="yes"/>
<layer number="44" name="Drills" color="7" fill="1" visible="no" active="yes"/>
<layer number="45" name="Holes" color="7" fill="1" visible="no" active="yes"/>
<layer number="46" name="Milling" color="3" fill="1" visible="no" active="yes"/>
<layer number="47" name="Measures" color="7" fill="1" visible="no" active="yes"/>
<layer number="48" name="Document" color="7" fill="1" visible="yes" active="yes"/>
<layer number="49" name="Reference" color="7" fill="1" visible="yes" active="yes"/>
<layer number="91" name="Nets" color="2" fill="1" visible="yes" active="yes"/>
<layer number="92" name="Busses" color="1" fill="1" visible="yes" active="yes"/>
<layer number="93" name="Pins" color="2" fill="1" visible="no" active="yes"/>
<layer number="94" name="Symbols" color="4" fill="1" visible="yes" active="yes"/>
<layer number="95" name="Names" color="7" fill="1" visible="yes" active="yes"/>
<layer number="96" name="Values" color="7" fill="1" visible="yes" active="yes"/>
<layer number="97" name="Info" color="7" fill="1" visible="yes" active="yes"/>
<layer number="98" name="Guide" color="6" fill="1" visible="yes" active="yes"/>
</layers>`;

/**
 * Generate EAGLE .lbr XML from parsed symbol data.
 *
 * @param {object} input
 * @param {string} input.symbolName
 * @param {string} input.description
 * @param {string} [input.referencePrefix='U']
 * @param {Array<{name: string, number: string, type: string, x: number, y: number, angle: number, length: number}>} input.pins
 * @param {object} input.body - Body rectangle { left, right, top, bottom }
 * @param {Array<{name: string, x: number, y: number, justify: string}>} [input.groupLabels]
 * @returns {string} Complete EAGLE .lbr XML content
 */
export function generateLbr(input) {
  const {
    symbolName,
    description = '',
    referencePrefix = 'U',
    pins,
    body,
    groupLabels = [],
  } = input;

  const lines = [];
  lines.push('<?xml version="1.0" encoding="utf-8"?>');
  lines.push('<!DOCTYPE eagle SYSTEM "eagle.dtd">');
  lines.push('<eagle version="9.6.2">');
  lines.push('<drawing>');
  lines.push('<settings><setting alwaysvectorfont="no"/></settings>');
  lines.push('<grid distance="0.1" unitdist="inch" unit="inch" style="lines" multiple="1" display="no" altdistance="0.01" altunitdist="inch" altunit="inch"/>');
  lines.push(LAYERS_XML);
  lines.push('<library>');
  lines.push(`<description>${escXml(symbolName)} — ${escXml(description)}</description>`);
  lines.push('<packages></packages>');
  lines.push('<symbols>');
  lines.push(`<symbol name="${escXml(symbolName)}">`);

  // Body rectangle (4 wires on layer 94)
  if (body) {
    lines.push(`  <wire x1="${body.left}" y1="${body.top}" x2="${body.right}" y2="${body.top}" width="0.254" layer="94"/>`);
    lines.push(`  <wire x1="${body.right}" y1="${body.top}" x2="${body.right}" y2="${body.bottom}" width="0.254" layer="94"/>`);
    lines.push(`  <wire x1="${body.right}" y1="${body.bottom}" x2="${body.left}" y2="${body.bottom}" width="0.254" layer="94"/>`);
    lines.push(`  <wire x1="${body.left}" y1="${body.bottom}" x2="${body.left}" y2="${body.top}" width="0.254" layer="94"/>`);
  }

  // >NAME and >VALUE labels
  const nameY = body ? body.top + 2.54 : 10;
  const valueY = body ? body.bottom - 2.54 : -10;
  lines.push(`  <text x="0" y="${nameY}" size="1.27" layer="95" align="bottom-center">&gt;NAME</text>`);
  lines.push(`  <text x="0" y="${valueY}" size="1.27" layer="96" align="top-center">&gt;VALUE</text>`);

  // Group labels on layer 94
  for (const label of groupLabels) {
    const align = label.justify === 'right' ? ' align="bottom-right"' : '';
    lines.push(`  <text x="${label.x}" y="${label.y}" size="0.762" layer="94"${align}>${escXml(label.name)}</text>`);
  }

  // Pins
  // Track NC pin names for deduplication
  const ncCounts = {};
  for (const pin of pins) {
    let pinName = pin.name;
    // EAGLE requires unique pin names — use @suffix for NC pins
    if (/^NC$/i.test(pinName)) {
      ncCounts.NC = (ncCounts.NC || 0) + 1;
      if (ncCounts.NC > 1) pinName = `NC@${ncCounts.NC}`;
    }

    const dir = PIN_TYPE_MAP[pin.type] || 'io';
    const rot = ANGLE_MAP[pin.angle] || '';
    const len = pinLengthKeyword(pin.length || 2.54);

    lines.push(`  <pin name="${escXml(pinName)}" x="${pin.x}" y="${pin.y}" length="${len}" direction="${dir}"${rot}/>`);
  }

  lines.push('</symbol>');
  lines.push('</symbols>');

  // Deviceset
  lines.push('<devicesets>');
  lines.push(`<deviceset name="${escXml(symbolName)}" prefix="${escXml(referencePrefix)}">`);
  lines.push(`  <description>${escXml(description)}</description>`);
  lines.push('  <gates>');
  lines.push(`    <gate name="G$1" symbol="${escXml(symbolName)}" x="0" y="0"/>`);
  lines.push('  </gates>');
  lines.push('  <devices>');
  lines.push('    <device name="">');
  lines.push('      <connects/>');
  lines.push('      <technologies><technology name=""/></technologies>');
  lines.push('    </device>');
  lines.push('  </devices>');
  lines.push('</deviceset>');
  lines.push('</devicesets>');

  lines.push('</library>');
  lines.push('</drawing>');
  lines.push('</eagle>');

  return lines.join('\n');
}