#!/usr/bin/env bash
# export.sh — KiCad Gerber export + pm4n generation for Anycubic Photon Mono 4
#
# Usage:
#   ./export.sh [OPTIONS] <path/to/board.kicad_pcb>
#
# Options:
#   --layers  LAYER,LAYER,...  KiCad layer names to export (default: F.Cu)
#   --invert  LAYER,LAYER,...  Layers to invert  (comma-separated)
#   --mirror  LAYER,LAYER,...  Layers to mirror  (comma-separated)
#   --exposure SECONDS         Exposure time in seconds (default: 60)
#   --dummy   FILE             Dummy .pm4n template (default: Dummy.pm4n beside this script)
#   --out     DIR              Output directory (default: ./output)
#   --dpmm    N                Render resolution in dots/mm (default: native 58.824)
#   --pos     X,Y              Board position on LCD in mm (default: centred)
#   --preview-scale N          Downsample preview PNG by N (default: 1 = full resolution)
#   --verbose                  Print detailed progress
#   -h, --help                 Show this help
#
# Normal output: one output filepath per layer.
# Verbose output: full progress from KiCad and the converter.
#
# Example:
#   ./export.sh --invert F.Cu,B.Mask --mirror F.Cu,F.Mask panel/board.kicad_pcb
#
# KiCad layer name → Gerber filename stem:
#   F.Cu    → F_Cu          B.Cu    → B_Cu
#   F.Mask  → F_Mask        B.Mask  → B_Mask
#   F.SilkS → F_Silkscreen  B.SilkS → B_Silkscreen
#   F.Paste → F_Paste       B.Paste → B_Paste
#   Edge.Cuts → Edge_Cuts
#   Front   → Front         Back    → Back

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PYTHON="${PYTHON:-python3}"
CONVERTER="$SCRIPT_DIR/gerber_to_pm4n.py"

# ---- defaults ----
LAYERS="F.Cu"
INVERT_LAYERS=""
MIRROR_LAYERS=""
EXPOSURE="60"
DUMMY="$SCRIPT_DIR/Dummy.pm4n"
OUT_DIR="./output"
DPMM=""
POS=""
VERBOSE=0
PREVIEW_SCALE=""

# ---- helpers ----
usage() {
    grep '^#' "$0" | sed 's/^# \{0,1\}//'
    exit 0
}

log() { [[ $VERBOSE -eq 1 ]] && echo "$@" || true; }

contains() {
    local list="$1" item="$2"
    echo "$list" | tr ',' '\n' | grep -qx "$item"
}

layer_to_filename() {
    case "$1" in
        F.Cu)      echo "Front" ;;
        B.Cu)      echo "Back" ;;
        F.SilkS)   echo "F_Silkscreen" ;;
        B.SilkS)   echo "B_Silkscreen" ;;
        Edge.Cuts) echo "Edge_Cuts" ;;
        *)         echo "${1//./_}" ;;
    esac
}

# ---- parse arguments ----
PCB_FILE=""
while [[ $# -gt 0 ]]; do
    case "$1" in
        --layers)   LAYERS="$2";         shift 2 ;;
        --invert)   INVERT_LAYERS="$2";  shift 2 ;;
        --mirror)   MIRROR_LAYERS="$2";  shift 2 ;;
        --exposure) EXPOSURE="$2";       shift 2 ;;
        --dummy)    DUMMY="$2";          shift 2 ;;
        --out)      OUT_DIR="$2";        shift 2 ;;
        --dpmm)     DPMM="$2";           shift 2 ;;
        --pos)           POS="$2";            shift 2 ;;
        --preview-scale) PREVIEW_SCALE="$2";  shift 2 ;;
        --verbose)  VERBOSE=1;           shift ;;
        -h|--help)  usage ;;
        -*)         echo "ERROR: unknown option: $1" >&2; exit 1 ;;
        *)          PCB_FILE="$1";       shift ;;
    esac
done

[[ -z "$PCB_FILE" ]] && { echo "ERROR: no .kicad_pcb file specified" >&2; exit 1; }
[[ ! -f "$PCB_FILE" ]] && { echo "ERROR: file not found: $PCB_FILE" >&2; exit 1; }
[[ ! -f "$DUMMY"    ]] && { echo "ERROR: Dummy.pm4n not found: $DUMMY" >&2; exit 1; }

BOARD_NAME="$(basename "$PCB_FILE" .kicad_pcb)"
GERBERS_DIR="$OUT_DIR/gerbers"
PM4N_DIR="$OUT_DIR/pm4n"
mkdir -p "$GERBERS_DIR" "$PM4N_DIR"

# ---- Step 1: export Gerbers ----
log "=== Exporting Gerbers ==="
log "  Board:  $PCB_FILE"
log "  Layers: $LAYERS"

kicad-cli pcb export gerbers \
    --output "$GERBERS_DIR" \
    --layers "$LAYERS" \
    --no-protel-ext \
    --subtract-soldermask \
    --no-netlist \
    "$PCB_FILE" \
    2>/dev/null

log ""

# ---- Step 2: convert to pm4n ----
log "=== Converting to .pm4n ==="

IFS=',' read -ra LAYER_LIST <<< "$LAYERS"
for LAYER in "${LAYER_LIST[@]}"; do
    LAYER_STEM="$(layer_to_filename "$LAYER")"
    GBR_FILE="$GERBERS_DIR/${BOARD_NAME}-${LAYER_STEM}.gbr"

    if [[ ! -f "$GBR_FILE" ]]; then
        echo "WARNING: Gerber not found for layer $LAYER (expected: $GBR_FILE)" >&2
        continue
    fi

    OUT_PM4N="$PM4N_DIR/${BOARD_NAME}-${LAYER_STEM}.pm4n"

    FLAGS=()
    contains "$INVERT_LAYERS" "$LAYER" && FLAGS+=(--invert)
    contains "$MIRROR_LAYERS" "$LAYER" && FLAGS+=(--mirror)
    [[ -n "$DPMM" ]] && FLAGS+=(--dpmm "$DPMM")
    [[ -n "$POS"  ]] && FLAGS+=(--pos "$POS")
    [[ -n "$PREVIEW_SCALE" ]] && FLAGS+=(--preview-scale "$PREVIEW_SCALE")
    [[ $VERBOSE -eq 1 ]] && FLAGS+=(--verbose)

    log "  $LAYER  →  $OUT_PM4N  [${FLAGS[*]:-} exposure=${EXPOSURE}s]"

    "$PYTHON" "$CONVERTER" \
        "$DUMMY" \
        "$GBR_FILE" \
        --output "$OUT_PM4N" \
        --exposure "$EXPOSURE" \
        "${FLAGS[@]}"
done

log "=== Done ==="