#!/system/bin/sh
# FlipperDroid WebUI — HTTP server with bridge API endpoints

WEBROOT="/data/adb/modules/flipperdroid/webroot"
CONFIG_DIR="/data/adb/flipperdroid"
CONFIG_FILE="$CONFIG_DIR/config.sh"
CMD_FIFO="$CONFIG_DIR/cmd_fifo"
RESP_DIR="$CONFIG_DIR/responses"
PORT=8089

mkdir -p "$CONFIG_DIR" "$RESP_DIR"
source "$CONFIG_FILE" 2>/dev/null
PORT="${WEBUI_PORT:-$PORT}"

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [webui] $1"; }

# Generate unique request ID
req_id() { echo "req_$(date +%s%N | cut -c1-16)_$$"; }

# Send command to bridge daemon via FIFO and wait for response
bridge_cmd() {
  local subsystem="$1"
  local action="$2"
  local params="${3:-}"
  local rid=$(req_id)
  local timeout=10

  echo "${rid}|${subsystem}|${action}|${params}" > "$CMD_FIFO" 2>/dev/null

  # Wait for response file
  local waited=0
  while [ ! -f "$RESP_DIR/${rid}" ] && [ $waited -lt $timeout ]; do
    sleep 0.1
    waited=$((waited + 1))
  done

  if [ -f "$RESP_DIR/${rid}" ]; then
    cat "$RESP_DIR/${rid}"
    rm -f "$RESP_DIR/${rid}"
  else
    echo "ERR:timeout"
  fi
}

# Read config as JSON
config_json() {
  source "$CONFIG_FILE" 2>/dev/null
  local status=$(cat "$CONFIG_DIR/status" 2>/dev/null || echo "unknown")
  local conn_type=$(cat "$CONFIG_DIR/conn_type" 2>/dev/null || echo "none")
  local flipper_dev=$(cat "$CONFIG_DIR/flipper_dev" 2>/dev/null || echo "")
  local flipper_product=$(cat "$CONFIG_DIR/flipper_product" 2>/dev/null || echo "")
  local flipper_serial=$(cat "$CONFIG_DIR/flipper_serial" 2>/dev/null || echo "")
  local flipper_version=$(cat "$CONFIG_DIR/flipper_version" 2>/dev/null || echo "")
  local flipper_caps=$(cat "$CONFIG_DIR/flipper_caps" 2>/dev/null || echo "")

  cat << EOF
{
  "status": "$status",
  "conn_type": "$conn_type",
  "conn_mode": "${CONN_MODE:-auto}",
  "device": "$flipper_dev",
  "product": "$flipper_product",
  "serial": "$flipper_serial",
  "firmware_version": "$flipper_version",
  "capabilities": "$flipper_caps",
  "config": {
    "auto_connect": ${AUTO_CONNECT:-1},
    "baud_rate": ${BAUD_RATE:-115200},
    "webui_port": ${WEBUI_PORT:-8089},
    "enable_gpio": ${ENABLE_GPIO:-1},
    "enable_subghz": ${ENABLE_SUBGHZ:-1},
    "enable_rfid": ${ENABLE_RFID:-1},
    "enable_nfc": ${ENABLE_NFC:-1},
    "enable_ir": ${ENABLE_IR:-1},
    "enable_ibutton": ${ENABLE_IBUTTON:-1},
    "enable_badusb": ${ENABLE_BADUSB:-0},
    "cpu_share": ${CPU_SHARE:-1},
    "cpu_share_threads": ${CPU_SHARE_THREADS:-2},
    "log_level": ${LOG_LEVEL:-2}
  }
}
EOF
}

# Get recent events as JSON array
events_json() {
  local count="${1:-20}"
  local events_file="$CONFIG_DIR/events"
  [ ! -f "$events_file" ] && echo "[]" && return

  echo -n "["
  local first=1
  tail -n "$count" "$events_file" | while IFS='|' read -r type data1 data2 ts; do
    [ $first -eq 1 ] && first=0 || echo -n ","
    echo -n "{\"type\":\"$type\",\"data\":\"$data1\",\"extra\":\"$data2\",\"timestamp\":$ts}"
  done
  echo "]"
}

#############################
# HTTP request handler
#############################

handle_request() {
  local method=""
  local path=""
  local content_length=0
  local body=""

  # Read request line
  read -r line
  method=$(echo "$line" | awk '{print $1}')
  path=$(echo "$line" | awk '{print $2}')

  # Read headers
  while read -r header; do
    header=$(echo "$header" | tr -d '\r')
    [ -z "$header" ] && break
    case "$header" in
      Content-Length:*|content-length:*)
        content_length=$(echo "$header" | awk '{print $2}')
        ;;
    esac
  done

  # Read body if POST
  if [ "$method" = "POST" ] && [ "$content_length" -gt 0 ] 2>/dev/null; then
    body=$(dd bs=1 count="$content_length" 2>/dev/null)
  fi

  # Route
  local response=""
  local content_type="application/json"
  local status="200 OK"

  case "$method $path" in
    # Static files
    "GET /"|"GET /index.html")
      content_type="text/html"
      response=$(cat "$WEBROOT/index.html" 2>/dev/null)
      ;;
    "GET /css/style.css")
      content_type="text/css"
      response=$(cat "$WEBROOT/css/style.css" 2>/dev/null)
      ;;
    "GET /js/app.js")
      content_type="application/javascript"
      response=$(cat "$WEBROOT/js/app.js" 2>/dev/null)
      ;;

    # API: Status & Config
    "GET /api/status")
      response=$(config_json)
      ;;
    "GET /api/events"*)
      response=$(events_json 50)
      ;;
    "GET /api/log")
      content_type="text/plain"
      response=$(tail -n 100 "$CONFIG_DIR/logs/flipperdroid.log" 2>/dev/null)
      ;;

    # API: System commands
    "POST /api/system/ping")
      response="{\"result\":\"$(bridge_cmd system ping)\"}"
      ;;
    "POST /api/system/version")
      response="{\"result\":\"$(bridge_cmd system version)\"}"
      ;;
    "POST /api/system/status")
      response="{\"result\":\"$(bridge_cmd system status)\"}"
      ;;

    # API: GPIO
    "POST /api/gpio/init")
      local pin=$(echo "$body" | grep -o '"pin":[0-9]*' | grep -o '[0-9]*')
      local mode=$(echo "$body" | grep -o '"mode":[0-9]*' | grep -o '[0-9]*')
      response="{\"result\":\"$(bridge_cmd gpio init "$pin,$mode")\"}"
      ;;
    "POST /api/gpio/write")
      local pin=$(echo "$body" | grep -o '"pin":[0-9]*' | grep -o '[0-9]*')
      local val=$(echo "$body" | grep -o '"value":[0-9]*' | grep -o '[0-9]*')
      response="{\"result\":\"$(bridge_cmd gpio write "$pin,$val")\"}"
      ;;
    "POST /api/gpio/read")
      local pin=$(echo "$body" | grep -o '"pin":[0-9]*' | grep -o '[0-9]*')
      response="{\"result\":\"$(bridge_cmd gpio read "$pin")\"}"
      ;;
    "POST /api/gpio/pwm")
      local pin=$(echo "$body" | grep -o '"pin":[0-9]*' | grep -o '[0-9]*')
      local freq=$(echo "$body" | grep -o '"freq":[0-9]*' | grep -o '[0-9]*')
      local duty=$(echo "$body" | grep -o '"duty":[0-9]*' | grep -o '[0-9]*')
      response="{\"result\":\"$(bridge_cmd gpio pwm "$pin,$freq,$duty")\"}"
      ;;
    "POST /api/gpio/adc")
      local pin=$(echo "$body" | grep -o '"pin":[0-9]*' | grep -o '[0-9]*')
      response="{\"result\":\"$(bridge_cmd gpio adc "$pin")\"}"
      ;;

    # API: SubGHz
    "POST /api/subghz/set_freq")
      local freq=$(echo "$body" | grep -o '"freq":[0-9]*' | grep -o '[0-9]*')
      response="{\"result\":\"$(bridge_cmd subghz set_freq "$freq")\"}"
      ;;
    "POST /api/subghz/tx")
      local data=$(echo "$body" | grep -o '"data":"[^"]*"' | cut -d'"' -f4)
      response="{\"result\":\"$(bridge_cmd subghz tx "$data")\"}"
      ;;
    "POST /api/subghz/rx_start")
      response="{\"result\":\"$(bridge_cmd subghz rx_start)\"}"
      ;;
    "POST /api/subghz/rx_stop")
      response="{\"result\":\"$(bridge_cmd subghz rx_stop)\"}"
      ;;
    "POST /api/subghz/get_rssi")
      response="{\"result\":\"$(bridge_cmd subghz get_rssi)\"}"
      ;;
    "POST /api/subghz/replay")
      local slot=$(echo "$body" | grep -o '"slot":[0-9]*' | grep -o '[0-9]*')
      response="{\"result\":\"$(bridge_cmd subghz replay "$slot")\"}"
      ;;

    # API: RFID
    "POST /api/rfid/read")
      response="{\"result\":\"$(bridge_cmd rfid read)\"}"
      ;;
    "POST /api/rfid/emulate")
      local data=$(echo "$body" | grep -o '"data":"[^"]*"' | cut -d'"' -f4)
      response="{\"result\":\"$(bridge_cmd rfid emulate "$data")\"}"
      ;;

    # API: NFC
    "POST /api/nfc/poll")
      response="{\"result\":\"$(bridge_cmd nfc poll)\"}"
      ;;
    "POST /api/nfc/read_full")
      response="{\"result\":\"$(bridge_cmd nfc read_full)\"}"
      ;;
    "POST /api/nfc/emulate")
      local data=$(echo "$body" | grep -o '"data":"[^"]*"' | cut -d'"' -f4)
      local type=$(echo "$body" | grep -o '"type":[0-9]*' | grep -o '[0-9]*')
      response="{\"result\":\"$(bridge_cmd nfc emulate "${data}${type}")\"}"
      ;;
    "POST /api/nfc/relay_start")
      response="{\"result\":\"$(bridge_cmd nfc relay_start)\"}"
      ;;
    "POST /api/nfc/relay_stop")
      response="{\"result\":\"$(bridge_cmd nfc relay_stop)\"}"
      ;;

    # API: IR
    "POST /api/ir/tx")
      local proto=$(echo "$body" | grep -o '"protocol":[0-9]*' | grep -o '[0-9]*')
      local addr=$(echo "$body" | grep -o '"address":[0-9]*' | grep -o '[0-9]*')
      local cmd=$(echo "$body" | grep -o '"command":[0-9]*' | grep -o '[0-9]*')
      response="{\"result\":\"$(bridge_cmd ir tx "$proto,$addr,$cmd")\"}"
      ;;
    "POST /api/ir/rx_start")
      response="{\"result\":\"$(bridge_cmd ir rx_start)\"}"
      ;;
    "POST /api/ir/rx_stop")
      response="{\"result\":\"$(bridge_cmd ir rx_stop)\"}"
      ;;
    "POST /api/ir/replay")
      local slot=$(echo "$body" | grep -o '"slot":[0-9]*' | grep -o '[0-9]*')
      response="{\"result\":\"$(bridge_cmd ir replay "$slot")\"}"
      ;;

    # API: iButton
    "POST /api/ibutton/read")
      response="{\"result\":\"$(bridge_cmd ibutton read)\"}"
      ;;
    "POST /api/ibutton/emulate")
      local data=$(echo "$body" | grep -o '"data":"[^"]*"' | cut -d'"' -f4)
      response="{\"result\":\"$(bridge_cmd ibutton emulate "$data")\"}"
      ;;

    # API: BadUSB
    "POST /api/badusb/start")
      response="{\"result\":\"$(bridge_cmd badusb start)\"}"
      ;;
    "POST /api/badusb/exec")
      local script=$(echo "$body" | grep -o '"script":"[^"]*"' | cut -d'"' -f4)
      response="{\"result\":\"$(bridge_cmd badusb exec "$script")\"}"
      ;;
    "POST /api/badusb/stop")
      response="{\"result\":\"$(bridge_cmd badusb stop)\"}"
      ;;

    # API: File operations on Flipper SD
    "POST /api/file/list")
      local fpath=$(echo "$body" | grep -o '"path":"[^"]*"' | cut -d'"' -f4)
      response="{\"result\":\"$(bridge_cmd file list "$fpath")\"}"
      ;;

    # API: Config update
    "POST /api/config")
      # Write config values back
      local key=$(echo "$body" | grep -o '"key":"[^"]*"' | cut -d'"' -f4)
      local value=$(echo "$body" | grep -o '"value":"[^"]*"' | cut -d'"' -f4)
      if [ -n "$key" ] && [ -n "$value" ]; then
        sed -i "s/^${key}=.*/${key}=${value}/" "$CONFIG_FILE"
        source "$CONFIG_FILE"
        response="{\"ok\":true}"
      else
        response="{\"ok\":false,\"error\":\"missing key or value\"}"
      fi
      ;;

    # API: Reconnect
    "POST /api/reconnect")
      echo "disconnected" > "$CONFIG_DIR/status"
      response="{\"ok\":true,\"message\":\"reconnecting...\"}"
      ;;

    # API: Stealth
    "GET /api/stealth/status")
      response=$(/system/bin/fd-stealth status 2>/dev/null || echo '{"error":"stealth not available"}')
      ;;
    "POST /api/stealth/apply")
      /system/bin/fd-stealth apply >> "$CONFIG_DIR/logs/stealth.log" 2>&1
      response="{\"ok\":true,\"message\":\"stealth applied\"}"
      ;;
    "POST /api/stealth/teardown")
      /system/bin/fd-stealth teardown >> "$CONFIG_DIR/logs/stealth.log" 2>&1
      response="{\"ok\":true,\"message\":\"stealth removed\"}"
      ;;
    "POST /api/stealth/hide")
      /system/bin/fd-stealth hide-dev >> "$CONFIG_DIR/logs/stealth.log" 2>&1
      response="{\"ok\":true,\"message\":\"device hidden\"}"
      ;;
    "POST /api/stealth/show")
      /system/bin/fd-stealth show-dev >> "$CONFIG_DIR/logs/stealth.log" 2>&1
      response="{\"ok\":true,\"message\":\"device visible\"}"
      ;;

    *)
      status="404 Not Found"
      response="{\"error\":\"not found\"}"
      ;;
  esac

  # Send HTTP response
  local content_length=${#response}
  printf "HTTP/1.1 %s\r\n" "$status"
  printf "Content-Type: %s\r\n" "$content_type"
  printf "Content-Length: %d\r\n" "$content_length"
  printf "Access-Control-Allow-Origin: *\r\n"
  printf "Connection: close\r\n"
  printf "\r\n"
  printf "%s" "$response"
}

#############################
# Start HTTP server
#############################

log "FlipperDroid WebUI starting on port $PORT"

# Use busybox nc or toybox for HTTP serving
while true; do
  handle_request | busybox nc -l -p "$PORT" -w 30 2>/dev/null || \
  handle_request | toybox nc -l -p "$PORT" -W 30 2>/dev/null || \
  handle_request | nc -l -p "$PORT" 2>/dev/null
done
