#!/bin/bash
# addfab - add 'fab' remote to an existing abf git repository

# ---------------- config definition (BEFORE sourcing lib) ----------------

config_order="ABF_URL_HTTPS ABF_URL_SSH ABF_OWNER ABF_PLATFORM \
FAB_URL_HTTPS FAB_URL_SSH FAB_OWNER FAB_PLATFORM FAB_BRANCHES \
GIT_PROTO"

declare -A config_defaults
config_defaults[ABF_URL_HTTPS]=https://abf.rosa.ru/
config_defaults[ABF_URL_SSH]=git@abf.rosa.ru:
config_defaults[ABF_OWNER]=import
config_defaults[ABF_PLATFORM]=rosa2023.1
config_defaults[FAB_URL_HTTPS]=https://gitea.rosa.ru/
config_defaults[FAB_URL_SSH]=ssh://git@gitea.rosa.ru:222/
config_defaults[FAB_OWNER]=rosalinux
config_defaults[FAB_PLATFORM]=rosa14
config_defaults[FAB_BRANCHES]="rosa14"
config_defaults[GIT_PROTO]=https

# ---------------- find and source library ----------------

script_dir=$(cd "$(dirname "$0")" && pwd)
lib_found=0
for libdir in "$script_dir" /usr/share/rosaclone; do
  if [ -f "$libdir/rosaclone-lib.sh" ]; then
    # shellcheck disable=SC1091
    . "$libdir/rosaclone-lib.sh"
    lib_found=1
    break
  fi
done
if [ "$lib_found" -eq 0 ]; then
  echo "error: rosaclone-lib.sh not found" >&2
  exit 1
fi

# ---------------- defaults (env already saved by library) ----------------

ABF_URL_HTTPS=""
ABF_URL_SSH=""
ABF_OWNER=""
ABF_PLATFORM=""

FAB_URL_HTTPS=""
FAB_URL_SSH=""
FAB_OWNER=""
FAB_PLATFORM=""
FAB_BRANCHES=""

GIT_PROTO="https"

# CLI overrides
opt_ssh=0
opt_https=0
opt_init_config=0
opt_debug=0

# ---------------- usage ----------------

usage() {
  cat <<'EOT'
usage:
  addfab [OPTIONS]

addfab - add 'fab' remote to an existing abf git repository

  Run this inside a git repository that was cloned from the old
  ABF (abf.rosa.ru, group 'import'). The script adds a second
  remote 'fab' pointing to the new ABF (gitea.rosa.ru, group
  'rosalinux') and fetches the branches listed in FAB_BRANCHES.

  The project name is taken from the current directory name.

  The repository must have a remote 'origin' with owner 'import'.
  Otherwise the script refuses to run: the tool only works with
  forks of the form import -> rosalinux.

  Branches from FAB_BRANCHES are created locally: from fab/<branch>
  if it exists there, otherwise from origin/<ABF_PLATFORM>.

protocol:
  --ssh                 use ssh (FAB_URL_SSH)
  --https, --http       use http(s) (FAB_URL_HTTPS)

  if neither is given, GIT_PROTO from config is used
  --ssh and --https/--http are mutually exclusive

common:
  --init-config         regenerate user config from defaults
  --debug               print debug info to stderr
  --help

config:
  /etc/rosaclone/config           (system defaults)
  ~/.config/rosaclone/config      (overrides system)

env:
  any config variable can be overridden by environment,
  e.g. FAB_BRANCHES="rosa14 rosa15" addfab
EOT
  exit 1
}

# ---------------- argument parsing ----------------

parse_args() {
  debug "parse_args: argv=$*"
  while [ $# -gt 0 ]; do
    debug "parse_args: arg='$1'"
    case "$1" in
      '--ssh' )                opt_ssh=1 ;;
      '--https' | '--http' )   opt_https=1 ;;
      '--init-config' )        opt_init_config=1 ;;
      '--debug' )              opt_debug=1 ;;
      '--help' | '-h')         usage ;;
      -*)
        die "unknown option: $1"
        ;;
      *)
        die "unexpected argument: $1"
        ;;
    esac
    shift
  done
}

# ---------------- validation ----------------

validate_modes() {
  debug "validate_modes: opt_ssh=$opt_ssh opt_https=$opt_https GIT_PROTO=$GIT_PROTO"

  if [ "$opt_ssh" -eq 1 ] && [ "$opt_https" -eq 1 ]; then
    die "only one of --ssh, --https is allowed"
  fi

  if [ "$opt_ssh" -eq 1 ]; then
    GIT_PROTO=ssh
  elif [ "$opt_https" -eq 1 ]; then
    GIT_PROTO=https
  fi
  debug "validate_modes: GIT_PROTO=$GIT_PROTO"

  case "$GIT_PROTO" in
    https|ssh) ;;
    *) die "unsupported GIT_PROTO: '$GIT_PROTO' (expected: https | ssh)" ;;
  esac

  [ -n "$ABF_OWNER" ] || die "ABF_OWNER is not set in config"
  [ "$ABF_OWNER" = "import" ] || die "ABF_OWNER must be 'import' (got '$ABF_OWNER')"

  [ -n "$FAB_OWNER" ] || die "FAB_OWNER is not set in config"
  [ "$FAB_OWNER" = "rosalinux" ] || die "FAB_OWNER must be 'rosalinux' (got '$FAB_OWNER')"
}

check_in_git_repo() {
  git rev-parse --git-dir >/dev/null 2>&1 || die "not a git repository"
  debug "in git repo: $(git rev-parse --show-toplevel)"
}

check_origin_remote() {
  local url owner
  url=$(git remote get-url origin 2>/dev/null) || die "no 'origin' remote found"
  owner=$(extract_owner_from_url "$url")
  debug "check_origin_remote: url='$url' owner='$owner'"
  [ "$owner" = "$ABF_OWNER" ] || die "origin owner is '$owner', expected '$ABF_OWNER'"
}

check_fab_remote_absent() {
  if git remote get-url fab >/dev/null 2>&1; then
    die "remote 'fab' already exists"
  fi
}

# ---------------- git operations ----------------

do_addfab() {
  local project fab_url
  project=$(basename "$PWD")
  debug "do_addfab: project='$project'"

  fab_url=$(build_url fab "$FAB_OWNER" "$project")
  debug "do_addfab: fab_url='$fab_url'"

  if ! setup_fab_remote "$fab_url"; then
    die "cannot set up fab remote '$fab_url'"
  fi

  ensure_fab_branches "origin/$ABF_PLATFORM"

  show_branches_info $FAB_BRANCHES
}

# ---------------- main ----------------

main() {
  case "${1:-}" in
    -h|--help|help)
      usage
      ;;
  esac

  check_git

  for a in "$@"; do
    case "$a" in
      --debug)       opt_debug=1 ;;
      --init-config) opt_init_config=1 ;;
    esac
  done

  debug "main: argv=$*"

  load_config
  parse_args "$@"
  print_config_vars

  if [ "$opt_init_config" -eq 1 ]; then
    return 0
  fi

  validate_modes
  check_in_git_repo
  check_origin_remote
  check_fab_remote_absent

  do_addfab
}

main "$@"
