#!/usr/bin/env bash

# Set this locally for Windows:
git config core.autocrlf input

set -e

# Set the GIT_SUBREPO_ROOT for testing.
source "$PWD"/.rc

# Get the location of this script
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )

BASHLIB=$(
  find "$PWD"/ -type d -name bin -o -type d -name lib | tr '\n' ':'
)
export BASHLIB

export PATH=$BASHLIB:$PATH
source bash+ :std

source 'lib/git-subrepo'

export TMP=$SCRIPT_DIR/tmp
rm -fr "$TMP"

#export GIT_EXEC_PATH=$PWD/lib:$(git --exec-path)
export UPSTREAM=$TMP/upstream
export OWNER=$TMP/owner
export COLLAB=$TMP/collab

mkdir -p "$UPSTREAM" "$OWNER" "$COLLAB"

cp -r test/repo/{foo,bar,init} "$UPSTREAM/"

DEFAULTBRANCH=$( git config --global --get init.defaultbranch || true )
[[ -z $DEFAULTBRANCH ]] && DEFAULTBRANCH="master"
export DEFAULTBRANCH

###
# Test helper functions:
###
clone-foo-and-bar() {
  (
    # foo will act as the main repo
    git clone "$UPSTREAM/foo" "$OWNER/foo"
    (
        cd "$OWNER/foo"
        git config core.autocrlf input
        git config user.name "FooUser"
        git config user.email "foo@foo"
    )
    # bar will act as the subrepo
    git clone "$UPSTREAM/bar" "$OWNER/bar"
    (
        cd "$OWNER/bar"
        git config core.autocrlf input
        git config user.name "BarUser"
        git config user.email "bar@bar"
    )
  ) &> /dev/null || die
}

subrepo-clone-bar-into-foo() {
  (
    cd "$OWNER/foo"
    git subrepo clone "$UPSTREAM/bar"
  ) &> /dev/null || die
}

add-new-files() {
  local file
  for file in "$@"; do
    echo "new file $file" > "$file"
    git add --force "$file"
  done
  git commit --quiet -m "add new file: $file" &> /dev/null
}

remove-files() {
  local file
  for file in "$@"; do
    git rm "$file"
  done
  git commit --quiet -m "Removed file: $file" &> /dev/null
}

modify-files() {
  local file
  for file in "$@"; do
    echo 'a new line' >> "$file"
    git add "$file"
  done
  git commit -m "modified file: $file"
}

modify-files-ex() {
  local file
  for file in "$@"; do
    echo "$file" >> "$file"
    git add "$file"
  done
  git commit -m "modified file: $file"
}

test-exists() {
  for f in "$@"; do
    if [[ $f =~ ^! ]]; then
      f=${f#!}
      if [[ $f =~ /$ ]]; then
        ok "$([ ! -d "$f" ])" \
          "Directory '$f' does not exist"
      else
        ok "$([ ! -f "$f" ])" \
          "File '$f' does not exist"
      fi
    else
      if [[ $f =~ /$ ]]; then
        ok "$([ -d "$f" ])" \
          "Directory '$f' exists"
      else
        ok "$([ -f "$f" ])" \
          "File '$f' exists"
      fi
    fi
  done
}

test-exists-in-index() {
  for f in "$@"; do
    if [[ $f =~ ^! ]]; then
      f=${f#!}
      if [[ $f =~ /$ ]]; then
        ok "$([ ! "$(git ls-tree --full-tree --name-only -r HEAD "$f")" ])" \
          "Directory '$f' does not exist in index"
      else
        ok "$([ ! "$(git ls-tree --full-tree --name-only -r HEAD "$f")" ])" \
          "File '$f' does not exist in index"
      fi
    else
      if [[ $f =~ /$ ]]; then
        ok "$([ "$(git ls-tree --full-tree --name-only -r HEAD "$f")" ])" \
          "Directory '$f' exists in index"
      else
        ok "$([ "$(git ls-tree --full-tree --name-only -r HEAD "$f")" ])" \
          "File '$f' exists in index"
      fi
    fi
  done
}

test-gitrepo-comment-block() {
  # shellcheck disable=2154
  is "$(grep -E '^;' "$gitrepo")" "\
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git \"subrepo\", and this file is maintained by the
; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme
;" \
    'Comment header block is correct'
}

test-gitrepo-field() {
  is "$(git config -f "$gitrepo" subrepo."$1")" \
    "$2" \
    ".gitrepo $1 is correct"
}

test-commit-count() {
  is "$(cd "$1"; git rev-list --count "$2")" \
    "$3" \
    "commit count is correct"
}

save-original-state() {
  original_head_ref=$(cd "$1"; cat .git/HEAD)
  original_branch=${original_head_ref#ref: refs/heads/}
  original_head_commit=$(cd "$1"; git rev-parse HEAD)
  original_gitrepo=$(cd "$1"; cat "$2"/.gitrepo)
}

assert-original-state() {
  current_head_ref=$(cd "$1"; cat .git/HEAD)
  current_branch=${current_head_ref#ref: refs/heads/}
  current_head_commit=$(cd "$1"; git rev-parse HEAD)
  current_gitrepo=$(cd "$1"; cat "$2"/.gitrepo)

  is "$current_head_ref" \
    "$original_head_ref" \
    "Current HEAD is still $original_head_ref"

  is "$current_branch" \
    "$original_branch" \
    "Current branch is still $original_branch"

  is "$current_head_commit" \
    "$original_head_commit" \
    "Current HEAD commit is still $original_head_commit"

  is "$current_gitrepo" \
    "$original_gitrepo" \
    "$2/.gitrepo has not changed"
}

catch() {
  local error=; error=$("$@" 2>&1 || true)
  echo "$error"
}

teardown() {
  rm -fr "$TMP"
}
