#!/usr/bin/env bash
# ──────────────────────────────────────────────────────────
# hhb — Hermes-Houdini Bridge Client
# Sends Python/hou commands to a running Houdini session
# via SSH + hcommand.
# ──────────────────────────────────────────────────────────
set -euo pipefail

HOST="${HHB_HOST:-niklas@192.168.178.39}"
PORT="${HHB_PORT:-12345}"
HCOMMAND="${HHB_HCOMMAND:-/opt/hfs21.0/bin/hcommand}"
WORKSPACE="${HHB_WORKSPACE:-/opt/data/projects/hermes-houdini-bridge}"

usage() {
    cat <<'EOF'
Usage: hhb <command> [args]

Commands:
  eval <python_code>     Execute Python code in the running Houdini session.
                         Example: hhb eval "print(hou.selectedNodes())"

  script <file.py>       Send a Python script file to Houdini and execute it.
                         Example: hhb script ./examples/create_pyro_setup.py

  get-selected           Print paths and types of selected nodes.
  get-param <parm>       Get value of a parameter on the first selected node.
  set-param <parm> <val> Set a parameter on the first selected node.
  get-inputs             Print input connections of the first selected node.
  status                 Check if the bridge port is open.
  help                   Show this help.

EOF
    exit 0
}

# ── Helpers ──────────────────────────────────────────────

run_remote_python() {
    # Write Python code to a temp file, execute via hcommand.
    # This avoids quoting hell with complex Python snippets.
    local python_code="$1"
    local tmpfile="/tmp/hhb_$$.py"

    # Upload script
    printf '%s' "$python_code" | ssh "$HOST" "cat > $tmpfile"

    # Execute via hscript's python command — reads file and execs
    local output
    output=$(ssh "$HOST" \
        "$HCOMMAND $PORT \"python exec(open('$tmpfile').read())\"" 2>&1) || {
        local rc=$?
        ssh "$HOST" "rm -f $tmpfile" 2>/dev/null
        echo "hhb: hcommand failed (exit $rc)" >&2
        echo "$output" >&2
        return $rc
    }

    # Cleanup
    ssh "$HOST" "rm -f $tmpfile" 2>/dev/null

    # hcommand output has a prefix line like "-> foobar", strip it
    echo "$output" | sed 's/^->\s*//'
}

# ── Commands ──────────────────────────────────────────────

cmd_status() {
    local output
    output=$(ssh "$HOST" "$HCOMMAND $PORT openport" 2>&1) || {
        echo "Bridge INACTIVE — Houdini not reachable or port $PORT closed."
        return 1
    }
    echo "$output" | sed 's/^->\s*//'
}

cmd_eval() {
    [[ $# -ge 1 ]] || { echo "Usage: hhb eval <python_code>"; exit 1; }
    run_remote_python "$*"
}

cmd_script() {
    [[ $# -ge 1 ]] || { echo "Usage: hhb script <file.py>"; exit 1; }
    local script_path="$1"
    [[ -f "$script_path" ]] || { echo "File not found: $script_path"; exit 1; }

    scp -q "$script_path" "$HOST:/tmp/hhb_script_$$.py"
    local output
    output=$(ssh "$HOST" \
        "$HCOMMAND $PORT \"python exec(open('/tmp/hhb_script_$$.py').read())\"" 2>&1) || {
        local rc=$?
        ssh "$HOST" "rm -f /tmp/hhb_script_$$.py" 2>/dev/null
        echo "hhb: hcommand failed (exit $rc)" >&2
        echo "$output" >&2
        return $rc
    }
    ssh "$HOST" "rm -f /tmp/hhb_script_$$.py" 2>/dev/null
    echo "$output" | sed 's/^->\s*//'
}

cmd_get_selected() {
    run_remote_python '
import hou
nodes = hou.selectedNodes()
if not nodes:
    print("No nodes selected.")
else:
    for n in nodes:
        print(f"{n.path():50s}  [{n.type().name()}]")
'
}

cmd_get_param() {
    [[ $# -ge 1 ]] || { echo "Usage: hhb get-param <parm_name>"; exit 1; }
    local parm="$1"
    run_remote_python "
import hou
nodes = hou.selectedNodes()
if not nodes:
    print('No nodes selected.')
else:
    p = nodes[0].parm('$parm')
    if p is None:
        print(f'Parameter \"$parm\" not found on {nodes[0].path()}')
    else:
        print(f'{nodes[0].path()}.{p.name()} = {p.eval()}')
"
}

cmd_set_param() {
    [[ $# -ge 2 ]] || { echo "Usage: hhb set-param <parm_name> <value>"; exit 1; }
    local parm="$1"
    local val="$2"
    run_remote_python "
import hou
nodes = hou.selectedNodes()
if not nodes:
    print('No nodes selected.')
else:
    p = nodes[0].parm('$parm')
    if p is None:
        print(f'Parameter \"$parm\" not found on {nodes[0].path()}')
    else:
        p.set('$val')
        print(f'{nodes[0].path()}.{p.name()} = {p.eval()}  ✓')
"
}

cmd_get_inputs() {
    run_remote_python '
import hou
nodes = hou.selectedNodes()
if not nodes:
    print("No nodes selected.")
else:
    for n in nodes:
        inputs = n.inputConnectors()
        print(f"\n{n.path()} [{n.type().name()}]")
        for i, conn in enumerate(inputs):
            in_nodes = n.inputConnections(i) if hasattr(n, "inputConnections") else []
            if in_nodes:
                for c in in_nodes:
                    print(f"  input {i} ← {c.inputNode().path()}  [{c.inputNode().type().name()}]")
            else:
                print(f"  input {i} ← (none)")
'
}

# ── Main ─────────────────────────────────────────────────

[[ $# -ge 1 ]] || usage

CMD="$1"
shift || true

case "$CMD" in
    eval)           cmd_eval "$@" ;;
    script)         cmd_script "$@" ;;
    get-selected)   cmd_get_selected ;;
    get-param)      cmd_get_param "$@" ;;
    set-param)      cmd_set_param "$@" ;;
    get-inputs)     cmd_get_inputs ;;
    status)         cmd_status ;;
    help|--help|-h) usage ;;
    *)
        echo "Unknown command: $CMD"
        usage
        ;;
esac
