/*
  Unity Transform After Effects Profile Export

  Usage:
  1. Open After Effects with a project that contains:
     - one source comp representing the content layout
     - one output comp representing the destination screen layout
  2. Run this script from File > Scripts > Run Script File...
  3. Select the source and output comps.
  4. Ensure the layers you want to map exist in both comps with matching names.
  5. Save the generated JSON and import it in Unity Transform.

  Notes:
  - Rotation/skew is not supported. Use axis-aligned layers for panel guides.
  - Hidden, disabled, camera, light, and null layers are ignored.
  - Bounds are calculated from sourceRectAtTime() where available, otherwise from layer.source size.
*/

(function () {
  function isGuideLayer(layer) {
    if (!layer || !layer.enabled) return false;
    if (layer.nullLayer) return false;
    if (layer instanceof CameraLayer || layer instanceof LightLayer) return false;
    return true;
  }

  function getCompItems() {
    var comps = [];
    for (var i = 1; i <= app.project.numItems; i++) {
      var item = app.project.item(i);
      if (item instanceof CompItem) comps.push(item);
    }
    return comps;
  }

  function getRectForLayer(layer) {
    var rect;
    try {
      rect = layer.sourceRectAtTime(layer.containingComp.time, false);
    } catch (err) {
      rect = null;
    }

    var width = rect ? rect.width : layer.source.width;
    var height = rect ? rect.height : layer.source.height;
    var left = rect ? rect.left : 0;
    var top = rect ? rect.top : 0;

    var scale = layer.property("Scale").value;
    var anchor = layer.property("Anchor Point").value;
    var pos = layer.property("Position").value;

    var scaleX = scale[0] / 100.0;
    var scaleY = scale[1] / 100.0;

    var x = Math.round(pos[0] + (left - anchor[0]) * scaleX);
    var y = Math.round(pos[1] + (top - anchor[1]) * scaleY);
    var w = Math.round(width * scaleX);
    var h = Math.round(height * scaleY);

    return { x: x, y: y, w: w, h: h };
  }

  function buildLayerMap(comp) {
    var map = {};
    for (var i = 1; i <= comp.numLayers; i++) {
      var layer = comp.layer(i);
      if (!isGuideLayer(layer)) continue;
      map[layer.name] = layer;
    }
    return map;
  }

  function compLabels(comps) {
    var labels = [];
    for (var i = 0; i < comps.length; i++) labels.push(comps[i].name);
    return labels;
  }

  function findCompByName(comps, name) {
    for (var i = 0; i < comps.length; i++) {
      if (comps[i].name === name) return comps[i];
    }
    return null;
  }

  function showDialog(comps) {
    var dlg = new Window("dialog", "Unity Transform Export");
    dlg.orientation = "column";
    dlg.alignChildren = ["fill", "top"];

    var intro = dlg.add("statictext", undefined, "Match layer names between source and output comps, then export JSON.");
    intro.characters = 60;

    var nameGroup = dlg.add("group");
    nameGroup.add("statictext", undefined, "Profile name");
    var nameInput = nameGroup.add("edittext", undefined, "");
    nameInput.characters = 40;

    var statusGroup = dlg.add("group");
    statusGroup.add("statictext", undefined, "Status");
    var statusInput = statusGroup.add("dropdownlist", undefined, ["awaiting", "approved", "rejected"]);
    statusInput.selection = 0;

    var sourceGroup = dlg.add("group");
    sourceGroup.add("statictext", undefined, "Source comp");
    var sourceList = sourceGroup.add("dropdownlist", undefined, compLabels(comps));
    sourceList.selection = 0;

    var outputGroup = dlg.add("group");
    outputGroup.add("statictext", undefined, "Output comp");
    var outputList = outputGroup.add("dropdownlist", undefined, compLabels(comps));
    outputList.selection = comps.length > 1 ? 1 : 0;

    var info = dlg.add("statictext", undefined, "Only enabled non-null layers are exported. Rotation is not supported.");
    info.characters = 60;

    var buttons = dlg.add("group");
    buttons.alignment = "right";
    buttons.add("button", undefined, "Cancel", { name: "cancel" });
    var ok = buttons.add("button", undefined, "Export", { name: "ok" });

    if (dlg.show() !== 1) return null;

    return {
      name: nameInput.text || outputList.selection.text,
      status: statusInput.selection.text,
      sourceName: sourceList.selection.text,
      outputName: outputList.selection.text
    };
  }

  function main() {
    if (!app.project) {
      alert("Open an After Effects project first.");
      return;
    }

    var comps = getCompItems();
    if (comps.length < 2) {
      alert("You need at least two comps in the project: a source comp and an output comp.");
      return;
    }

    var selection = showDialog(comps);
    if (!selection) return;

    var sourceComp = findCompByName(comps, selection.sourceName);
    var outputComp = findCompByName(comps, selection.outputName);
    if (!sourceComp || !outputComp) {
      alert("Could not resolve the selected comps.");
      return;
    }

    var sourceMap = buildLayerMap(sourceComp);
    var panels = [];
    var missing = [];

    for (var i = 1; i <= outputComp.numLayers; i++) {
      var outputLayer = outputComp.layer(i);
      if (!isGuideLayer(outputLayer)) continue;
      var sourceLayer = sourceMap[outputLayer.name];
      if (!sourceLayer) {
        missing.push(outputLayer.name);
        continue;
      }
      panels.push({
        id: outputLayer.name,
        src: getRectForLayer(sourceLayer),
        dst: getRectForLayer(outputLayer)
      });
    }

    if (!panels.length) {
      alert("No matching layers were found between the selected comps.");
      return;
    }

    var payload = {
      name: selection.name,
      version: 1,
      source: {
        width: sourceComp.width,
        height: sourceComp.height
      },
      output: {
        width: outputComp.width,
        height: outputComp.height
      },
      fps: Math.round(outputComp.frameRate),
      status: selection.status,
      panels: panels
    };

    var file = File.saveDialog("Save Unity Transform profile JSON", "JSON:*.json");
    if (!file) return;

    file.encoding = "UTF-8";
    file.open("w");
    file.write(JSON.stringify(payload, null, 2));
    file.close();

    var message = "Exported " + panels.length + " panel(s) to:\\n" + file.fsName;
    if (missing.length) {
      message += "\\n\\nSkipped output layers with no matching source layer:\\n- " + missing.join("\\n- ");
    }
    alert(message);
  }

  app.beginUndoGroup("Unity Transform Export");
  try {
    main();
  } finally {
    app.endUndoGroup();
  }
})();
