#!/bin/bash

set -e

if [ -z "$1" ]; then
  echo "Output directory argument is required"
  exit 1
fi

function abspath() {
    # generate absolute path from relative path
    # $1     : relative filename
    # return : absolute path
    if [ -d "$1" ]; then
        # dir
        (cd "$1"; pwd)
    elif [ -f "$1" ]; then
        # file
        if [[ $1 == */* ]]; then
            echo "$(cd "${1%/*}"; pwd)/${1##*/}"
        else
            echo "$(pwd)/$1"
        fi
    fi
}

if [ ! -d "$1" ]; then
  mkdir "$1"
fi
OUT=$(abspath $1)
SRCROOT=$(abspath $(dirname $0)/..)
cd ${SRCROOT}

mkdir -p ${OUT}/tests


function build_and_test_python() {
  local srcdir=$1
  local destdir=$2

  echo "================= Testing python ${srcdir} ================"
  mkdir -p ${destdir}/
  virtualenv ${destdir}/
  source ${destdir}/bin/activate
  if [ -f ${srcdir}/requirements.txt ]; then
    pip install \
        --extra-index-url https://pypi.internal.justin.tv/simple/ \
        -r ${srcdir}/requirements.txt
  fi
  cp -r ${srcdir}/{*.py,run_tests.sh,code} ${destdir}/
  ${SRCROOT}/scripts/compile_python_proto.sh ${destdir}
  if [ -f ${destdir}/run_tests.sh ]; then
    (
      cd ${destdir} && ./run_tests.sh
    )
  fi
  echo "========================================================================"
  echo
}


function build_and_test_lambda() {
  local srcdir=$1
  local lambdapkgdir=${OUT}/$(basename $srcdir)
  local destdir=${lambdapkgdir}_venv

  build_and_test_python ${srcdir} ${destdir}

  echo "======= Building python ${lambdapkgdir} package directory ======="
  mkdir -p ${lambdapkgdir}/
  cp ${destdir}/*.py ${lambdapkgdir}/
  cp -r ${destdir}/code ${lambdapkgdir}/
  cp -r ${destdir}/google ${lambdapkgdir}/
  cp -r ${destdir}/lib/python2.7/site-packages/* ${lambdapkgdir}/
  echo "========================================================================"
  echo
}

build_and_test_lambda ${SRCROOT}/aws_lambda


echo "==================== Building and testing React Code ====================="
# For the most part, we don't bother re-generating code on every build but
# the Javascript/Node/React UI is fairly complicated. We will build it and
# package it into a "bindata.go" for serving on every build to make
# sure it's up to date.
# This is also where we would run any tests.
go generate ./client/web
cp -a ./client/web/test_results/. ${OUT}/tests/
echo "========================================================================"
echo


# Lint, test, and generate coverage.
# proto and mocks packages are skipped because they are generated sources.
echo "===================== Linting and testing Go Code ======================"
PKGS=$(go list -f '{{.ImportPath}}' -- $(glide novendor) | grep -v -E 'rockpaperscissors/(proto|internal/mocks)')
for pkg in $PKGS; do
  echo "Linting: ${pkg}"
  golint ${pkg} || true  # Don't bail due to a linter warning

  echo "Static error analysis: ${pkg}"
  go vet "${pkg}"
  errcheck "${pkg}"

  echo "Testing and generating coverage for: ${pkg}"
  coverage_prefix=${OUT}/${pkg//\//_}
  # Note: since "set -o pipefail" isn't being used, non-zero exit from "go test" doesn't make script exit.
  go test -coverprofile=${coverage_prefix}.out ${pkg} -v | go-junit-report > ${OUT}/tests/${pkg//\//_}.xml
  if [[ -f ${coverage_prefix}.out ]]; then
    go tool cover -func=${coverage_prefix}.out
    go tool cover -html=${coverage_prefix}.out -o ${coverage_prefix}.html
  fi
  echo
done
echo "========================================================================"
echo

echo "=========================== Building Go Code ==========================="
go build $(glide novendor)

CMD_PKGS=$(go list -f '{{if eq .Name "main"}}{{.ImportPath}}{{end}}' -- $(glide novendor))
for cmd in $CMD_PKGS; do
  GOBIN="${OUT}" go install "${cmd}"
done
echo "========================================================================"
echo

twerk get-tests ${OUT}/tests --output ${OUT}
