#!/usr/bin/env bash

version="1.1.0"

# -e : Exit immediately if a simple command exits with a non-zero status.
set -e

validate_url() {
  url="$1"
  # supports following URLs
  #  HTTP: https://github.com/*/*.git
  #  SSH:  git@github.com:*/*.git
  #  Git:  git://github.com/*/*.git
  valid_url=$(echo "$1" | grep '^\(https://github.com/\|git@github.com:\|git://github.com/\)[^/]*/[^/]*.git$' || true)
  if [ -z "$valid_url" ]; then
    echo "fakegit: Specified invalid GitHub URL \`$url'" >&2
    exit 1
  fi
}

fetch_command() {
  if type curl &>/dev/null; then
    echo "curl" "-L" "$@"
  elif type wget &>/dev/null; then
    echo "wget" "-O-" "$@"
  fi
}

log()  { printf "fakegit: %b\n" "$*" >&2 ; return $? ;  }

fail() { log "ERROR: $*\n" ; exit 1 ; }

# public
fakegit_ls_files() {
  dir="${1:-.}"

  if [ -f ".gitignore" ]; then
    find "$dir" -type f $(printf "! -path %s " $(<.gitignore))
  else
    find "$dir" -type f
  fi | cut -c$((${#dir}+2))-
}

fakegit_clone() {
  local branch_name="master"

  if [ "$1" = "-b" ] || [ "$1" = "--branch" ]; then
    branch_name="$2"
    if [ -z "$branch_name" ] ; then
      fail "switch \`$1' requires a value"
      exit 1
    fi
    shift 2
  fi

  local git_repo="$1"

  if [ -z "$git_repo" ]; then
    echo "usage: $0 clone [-b <branch_name>] <GitHub Repository URL> [<directory>]" >&2
    exit 1
  fi

  validate_url $git_repo
  # Git URL -> HTTP URL
  local https_repo="${git_repo/#git:/https:}"
  # SSH URL -> HTTP URL
  https_repo="${https_repo/#git@github.com:/https://github.com/}"
  local svn_repo="${https_repo%*.git}"
  local proj_name="${svn_repo##*/}"
  local dir="${2:-$proj_name}"

  if type svn &>/dev/null; then
    local svn_dir="trunk"
    if [ "$branch_name" != "master" ] ; then
      svn_dir="branches/${branch_name}"
    fi
    local svn_command="svn checkout ${svn_repo}/${svn_dir} $dir"
    log "Instaed of git, executing:\n" "$svn_command\n"
    echo $svn_command
    printf "\n"
    log "See details for GitHub Subversion support:\n" "https://github.com/blog/966-improved-subversion-client-support"
  else
    local fetch_command=$(fetch_command "${svn_repo}/tarball/${branch_name}" || true)
    local extract_command="tar xzf - --strip-components 1 -C $dir"
    if [ -z "$fetch_command" ] ; then
      fail "No download command found.\nPlease install one of \`svn', \`curl' or \`wget' and try again"

      exit 1
    fi
    mkdir -p $dir
    log "Instaed of git, executing:\n" $fetch_command "|" $extract_command
    $fetch_command | $extract_command
  fi
}

fakegit_help() {
  case "$1" in
  "" )
    echo "usage: fakegit <command> [<args>]"
    ;;
  "clone" )
    echo "usage: fakegit clone <GitHub repository> [<directory>]"
    ;;
  * )
    command_path="$(command -v "fakegit_$1" || true)"
    if [ -n "$command_path" ]; then
      echo "Sorry, the \`$1' command isn't documented yet."
      echo
      echo "You can view the command's source here:"
      echo "$command_path"
      echo
    else
      echo "fakegit: no such command \`$1'"
    fi
  esac
}

command="$1"
case "$command" in
  "" | "-h" | "--help" )
    echo -e "[fake]git ${version}\n$(fakegit_help)" >&2
    ;;
  * )
    command_path="$(command -v "fakegit_${command/-/_}" || true)"
    if [ -z "$command_path" ]; then
      echo "fakegit: Unsupported command \`$command'" >&2
      exit 1
    fi

    shift 1
    "$command_path" "$@"
  ;;
esac
