#!/usr/bin/env bash

set -x -u -e -o pipefail

# Setup environment
readonly thisDir=$(cd $(dirname $0); pwd)
cd "$thisDir/../.."

function getBuildVersion {
  # Example of `STABLE_PROJECT_VERSION` for snapshots is: `21.0.0-next.7+sha-7134dfe`
  local buildVersion=$(
    pnpm --silent ng-dev release build-env-stamp --mode=snapshot |
      grep STABLE_PROJECT_VERSION |
      sed 's/STABLE_PROJECT_VERSION //'
  )

  if [[ -z "${buildVersion}" ]]; then
    echo "Error: Unable to find the build version." 1>&2
    exit 1;
  fi

  echo $buildVersion;
}

function publishRepo {
  COMPONENT=$1
  ARTIFACTS_DIR=$2
  BUILD_REPO=${3:-"${COMPONENT}-builds"}

  REPO_DIR="$(pwd)/tmp/${BUILD_REPO}"
  REPO_URL="https://github.com/${ORG}/${BUILD_REPO}.git"

  if [ -n "${CREATE_REPOS:-}" ]; then
    curl -u "$ORG:$TOKEN" https://api.github.com/user/repos \
         -d '{"name":"'$BUILD_REPO'", "auto_init": true}'
  fi

  echo "Pushing build artifacts to ${ORG}/${BUILD_REPO}"

  # create local repo folder and clone build repo into it
  rm -rf $REPO_DIR
  mkdir -p ${REPO_DIR}

  echo "Starting cloning process of ${REPO_URL} into ${REPO_DIR}.."

  (
    if [[ $(git ls-remote --heads ${REPO_URL} ${BRANCH}) ]]; then
      echo "Branch ${BRANCH} already exists. Cloning that branch."
      git clone ${REPO_URL} ${REPO_DIR} --depth 100 --branch ${BRANCH}

      cd ${REPO_DIR}
      echo "Cloned repository and switched into the repository directory (${REPO_DIR})."
    else
      echo "Branch ${BRANCH} does not exist on ${BUILD_REPO} yet."
      echo "Cloning default branch and creating branch '${BRANCH}' on top of it."

       git clone ${REPO_URL} ${REPO_DIR} --depth 100
      cd ${REPO_DIR}

      echo "Cloned repository and switched into directory. Creating new branch now.."

      git checkout -b ${BRANCH}
    fi
  )

  # copy over build artifacts into the repo directory
  rm -rf $REPO_DIR/*
  cp -R $ARTIFACTS_DIR/* $REPO_DIR/

  if [[ ${CI} ]]; then
    (
      cd $REPO_DIR && \
      git config credential.helper "store --file=$HOME/.git_credentials"
    )
  fi
  echo `date` > $REPO_DIR/BUILD_INFO
  echo $SHA >> $REPO_DIR/BUILD_INFO

  (
    cd $REPO_DIR && \
    git config user.name "${COMMITTER_USER_NAME}" && \
    git config user.email "${COMMITTER_USER_EMAIL}" && \
    git add --all && \
    git commit -m "${COMMIT_MSG}" --quiet && \
    git tag "${BUILD_VER}" --force && \
    git push origin "${BRANCH}" --tags --force
  )
}

# Publish all individual packages from packages-dist.
function publishPackages {
  GIT_SCHEME=$1
  PKGS_DIST=$2
  BRANCH=$3
  BUILD_VER=$4

  for dir in $PKGS_DIST/*/
  do
    if [[ ! -f "$dir/package.json" ]]; then
      # Only publish directories that contain a `package.json` file.
      echo "Skipping $dir, it does not contain a package to be published."
      continue
    fi

    COMPONENT="$(basename ${dir})"

    # Replace _ with - in component name.
    COMPONENT="${COMPONENT//_/-}"
    JS_BUILD_ARTIFACTS_DIR="${dir}"

    if [[ "$GIT_SCHEME" == "ssh" ]]; then
      REPO_URL="git@github.com:${ORG}/${COMPONENT}-builds.git"
    elif [[ "$GIT_SCHEME" == "http" ]]; then
      REPO_URL="https://github.com/${ORG}/${COMPONENT}-builds.git"
    else
      die "Don't have a way to publish to scheme $GIT_SCHEME"
    fi

    publishRepo "${COMPONENT}" "${JS_BUILD_ARTIFACTS_DIR}"
  done

  echo "Finished publishing build artifacts"
}

# Packaging and publishing dev-skills.
function publishDevSkills {
  GIT_SCHEME=$1
  BRANCH=$2
  BUILD_VER=$3

  echo "Publishing dev-skills..."

  # Create a temporary tree-ish that includes uncommitted changes.
  # If no changes exist, git stash create returns empty, so we fall back to HEAD.
  tree_ish=$(git stash create)
  if [ -z "$tree_ish" ]; then
    tree_ish="HEAD"
  fi

  SKILLS_DIST="$(pwd)/dist/dev-skills-dist"
  echo "Packaging dev-skills into $SKILLS_DIST..."
  rm -rf "$SKILLS_DIST"
  mkdir -p "$SKILLS_DIST"
  
  # This ensures that individual skills (like angular-developer) are at the root of the destination repo.
  git archive "$tree_ish":"skills/dev-skills" | tar -x -C "$SKILLS_DIST"

  publishRepo "skills" "${SKILLS_DIST}" "skills"
}

function publishAllBuilds() {
  GIT_SCHEME="$1"

  SHA=`git rev-parse HEAD`
  COMMIT_MSG=`git log --oneline -1`
  COMMITTER_USER_NAME=`git --no-pager show -s --format='%cN' HEAD`
  COMMITTER_USER_EMAIL=`git --no-pager show -s --format='%cE' HEAD`
  PACKAGES_DIST="$(pwd)/dist/packages-dist"

  local buildVersion=`getBuildVersion`

  publishPackages $GIT_SCHEME $PACKAGES_DIST $CUR_BRANCH $buildVersion
  publishDevSkills $GIT_SCHEME $CUR_BRANCH $buildVersion
}

# See docs/DEVELOPER.md for help
CUR_BRANCH=$(git symbolic-ref --short HEAD)
if [ $# -gt 0 ]; then
  ORG=$1
  publishAllBuilds "ssh"
else
  ORG="angular"
  publishAllBuilds "http"
fi
