#!/bin/sh

set -e

APP_URL="http://fw.koolcenter.com/binary/LinkEase/alpha/raspi.lowmem.arm"
HEIF_URL="http://fw.koolcenter.com/binary/LinkEase/alpha/heif-converter.arm"
MEDIA_URL="http://fw.koolcenter.com/binary/LinkEase/alpha/linkease-media.arm"
INSTALL_NAME="linkease"
MIN_SPEED_MB=10
SPEED_TEST_MB=16
MEMORY_MAX_KB=327680

usage() {
  echo "Usage: $0 RUN_PATH"
  exit 1
}

log() {
  echo "[linkease-installer] $*"
}

fail() {
  echo "[linkease-installer] ERROR: $*" >&2
  exit 1
}

require_cmd() {
  command -v "$1" >/dev/null 2>&1 || fail "missing command: $1"
}

parse_speed_mb() {
  printf '%s\n' "$1" | awk '
    function print_value(raw_value, raw_unit) {
      value = raw_value + 0
      unit = raw_unit
      if (unit == "bytes") {
        value = value / 1048576
      } else if (unit == "kB" || unit == "KiB") {
        value = value / 1024
      } else if (unit == "MB" || unit == "MiB") {
        value = value
      } else if (unit == "GB" || unit == "GiB") {
        value = value * 1024
      } else if (unit == "TB" || unit == "TiB") {
        value = value * 1024 * 1024
      } else {
        exit 1
      }
      printf "%.2f\n", value
      found = 1
      exit
    }
    {
      line = $0
      gsub(/[，,]/, " ", line)
      count = split(line, parts, /[[:space:]]+/)
      for (i = 1; i <= count; i++) {
        token = parts[i]
        gsub(/,/, "", token)
        if (token ~ /^[0-9.]+(bytes|[kMGT]i?B)\/s$/) {
          unit = token
          sub(/^[0-9.]+/, "", unit)
          sub(/\/s$/, "", unit)
          value = token
          sub(/(bytes|[kMGT]i?B)\/s$/, "", value)
          print_value(value, unit)
        }
        if (token ~ /^(bytes|[kMGT]i?B)\/s$/ && i > 1) {
          value = parts[i - 1]
          gsub(/,/, "", value)
          unit = token
          sub(/\/s$/, "", unit)
          if (value ~ /^[0-9.]+$/) {
            print_value(value, unit)
          }
        }
      }
    }
    END {
      if (!found) {
        exit 1
      }
    }
  '
}

check_min_speed() {
  speed="$1"
  threshold="$2"
  awk -v speed="$speed" -v threshold="$threshold" 'BEGIN { exit !(speed + 0 >= threshold + 0) }'
}

download_to() {
  url="$1"
  target="$2"
  tmp_target="${target}.download"
  rm -f "$tmp_target"
  log "downloading $(basename "$target")"
  wget -O "$tmp_target" "$url"
  chmod 755 "$tmp_target"
  mv "$tmp_target" "$target"
}

generate_run_script() {
  run_script="$1"
  cat > "$run_script" <<EOF
#!/bin/sh

set -e

SCRIPT_DIR=\$(CDPATH= cd -- "\$(dirname -- "\$0")" && pwd)
LOG_DIR="\$SCRIPT_DIR/logs"
CACHE_DIR="\$SCRIPT_DIR/cache"

mkdir -p "\$LOG_DIR" "\$CACHE_DIR"

export GOMEMLIMIT=160MiB
export GOGC=50
export GODEBUG=madvdontneed=1
export PATH="\$SCRIPT_DIR:\$PATH"
export LINKEASE_CONFIG="\$SCRIPT_DIR"

ulimit -v ${MEMORY_MAX_KB} >/dev/null 2>&1 || true

cd "\$SCRIPT_DIR"
exec "\$SCRIPT_DIR/linkease" "\$@" >> "\$LOG_DIR/client.log" 2>&1
EOF
  chmod 755 "$run_script"
}

[ $# -eq 1 ] || usage

RUN_PATH="$1"
INSTALL_DIR="$RUN_PATH/$INSTALL_NAME"
WRITE_TEST_FILE="$RUN_PATH/.linkease_write_test.$$"
EXEC_TEST_FILE="$RUN_PATH/.linkease_exec_test.$$"
SPEED_TEST_FILE="$RUN_PATH/.linkease_speed_test.$$"

cleanup() {
  rm -f "$WRITE_TEST_FILE" "$EXEC_TEST_FILE" "$SPEED_TEST_FILE"
}

trap cleanup EXIT INT TERM

require_cmd wget
require_cmd dd
require_cmd awk
require_cmd chmod
require_cmd mkdir
require_cmd rm
require_cmd touch
require_cmd uname

[ -d "$RUN_PATH" ] || fail "RUN_PATH does not exist: $RUN_PATH"

ARCH=$(uname -m 2>/dev/null || echo unknown)
case "$ARCH" in
  arm*|xscale)
    ;;
  *)
    log "warning: current machine arch is $ARCH, expected linux arm"
    ;;
esac

touch "$WRITE_TEST_FILE" || fail "RUN_PATH is not writable: $RUN_PATH"
rm -f "$WRITE_TEST_FILE"

cat > "$EXEC_TEST_FILE" <<'EOF'
#!/bin/sh
exit 0
EOF
chmod 755 "$EXEC_TEST_FILE"
"$EXEC_TEST_FILE" >/dev/null 2>&1 || fail "RUN_PATH is not executable (maybe mounted with noexec): $RUN_PATH"
rm -f "$EXEC_TEST_FILE"

mkdir -p "$INSTALL_DIR/logs" "$INSTALL_DIR/cache"

log "testing USB write speed"
WRITE_OUT=$(dd if=/dev/zero of="$SPEED_TEST_FILE" bs=1M count=$SPEED_TEST_MB conv=fsync 2>&1) || fail "write speed test failed"
WRITE_MB=$(parse_speed_mb "$WRITE_OUT") || fail "unable to parse write speed"
check_min_speed "$WRITE_MB" "$MIN_SPEED_MB" || fail "write speed ${WRITE_MB}MB/s is below ${MIN_SPEED_MB}MB/s"

log "testing USB read speed"
READ_OUT=$(dd if="$SPEED_TEST_FILE" of=/dev/null bs=1M 2>&1) || fail "read speed test failed"
READ_MB=$(parse_speed_mb "$READ_OUT") || fail "unable to parse read speed"
check_min_speed "$READ_MB" "$MIN_SPEED_MB" || fail "read speed ${READ_MB}MB/s is below ${MIN_SPEED_MB}MB/s"
rm -f "$SPEED_TEST_FILE"

download_to "$APP_URL" "$INSTALL_DIR/linkease"
download_to "$HEIF_URL" "$INSTALL_DIR/heif-converter"
download_to "$MEDIA_URL" "$INSTALL_DIR/linkease-media"
generate_run_script "$INSTALL_DIR/run.sh"

log "install complete"
log "install dir: $INSTALL_DIR"
log "write speed: ${WRITE_MB}MB/s"
log "read speed: ${READ_MB}MB/s"
log "run with: $INSTALL_DIR/run.sh"
