#!/bin/bash

function updateStatus {
  STATUS=$1
  CTX=$2
  DESC=$3

  SHA=$TRAVIS_COMMIT
  if [ ! -z "$TRAVIS_PULL_REQUEST_SHA" ]; then
    SHA=$TRAVIS_PULL_REQUEST_SHA
  fi

  TRAVIS_JOB_URL="https://travis-ci.com/atom/github/jobs/$TRAVIS_JOB_ID"
  GH_API_URL="https://api.github.com/repos/atom/github/statuses/$SHA"
  curl -H "Authorization: token $GITHUB_TOKEN" --data "{\"state\": \"$STATUS\", \"target_url\": \"$TRAVIS_JOB_URL\", \"description\": \"$DESC\", \"context\": \"schema/$CTX\"}" $GH_API_URL
}

function checkForSchemaChanges {
  CTX="$TRAVIS_EVENT_TYPE"

  # Only check schema changes on a push build on MacOS
  if [ "${CTX}" != "push" ] && [ "${CTX}" != "cron" ]
  then
    exit
  fi

  if [ "${TRAVIS_OS_NAME}" != "osx" ]
  then
    exit
  fi

  if [ -z "${GITHUB_TOKEN}" ]
  then
    exit
  fi

  updateStatus "pending" $CTX "Checking for GraphQL Schema Changes"

  SCHEMA_BRANCH_NAME=auto-schema-update-${TRAVIS_BUILD_NUMBER:-0}

  git fetch --depth=1 origin +refs/heads/master:refs/remotes/origin/master
  git merge origin/master

  trap "updateStatus 'failure' $CTX 'Script failure' ; exit 1" ERR
  time npm install

  echo "Fetching schema..."
  time npm run fetch-schema
  sleep 2

  echo "Checking for schema changes..."

  git status > /dev/null
  if ! git diff-index HEAD --quiet -- graphql/schema.graphql
  then
    echo "Schema is out of date:"
    echo
    git --no-pager diff -- graphql/schema.graphql

    # Search for an existing pull request
    PR_TITLE="GraphQL schema update"
    SEARCH_API_URL="https://api.github.com/search/issues"
    SEARCH_QUERY="type:pr+state:open+repo:atom%2Fgithub+in:title+'${PR_TITLE// /+}'"
    RESPONSE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "${SEARCH_API_URL}?q=${SEARCH_QUERY}" | jq .total_count)
    if [ "${RESPONSE}" != "0" ]
    then
      echo "...but a pull request already exists"
      updateStatus "success" $CTX "Schema pull request already exists"
      exit 0
    else
      echo "no schema pull request exists yet"
    fi

    # Push this branch and create a pull request
    REPO=$(git config remote.origin.url)
    SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:}

    # Move the updated schema to a new branch created from master, commit, and push.
    git stash --all
    git checkout --no-track -B ${SCHEMA_BRANCH_NAME} origin/master
    git stash pop

    git config user.name "Travis CI"
    git config user.email "atom-build@users.noreply.github.com"

    git add graphql/schema.graphql graphql/schema.json
    git commit -m 'automated GraphQL schema update'

    git push -f ${SSH_REPO} ${SCHEMA_BRANCH_NAME}

    TRAVIS_JOB_URL="https://travis-ci.com/atom/github/jobs/$TRAVIS_JOB_ID"
    GH_API_URL="https://api.github.com/repos/atom/github/pulls"
    curl -H "Authorization: token $GITHUB_TOKEN" ${GH_API_URL} --data "\
{\
  \"title\": \"${PR_TITLE}\",\
  \"head\": \"${SCHEMA_BRANCH_NAME}\",\
  \"base\": \"master\",\
  \"body\": \"Automated schema update submitted by [a Travis build](${TRAVIS_JOB_URL}).\"\
}"
    echo "Pull request created."
    updateStatus "success" $CTX "Schema update pull request created"
    exit
  fi
  updateStatus "success" $CTX "Schema is already up to date"
  echo "Schema is up to date"
  exit
}

function runTests {
  echo "Downloading latest Atom release..."
  ATOM_CHANNEL="${ATOM_CHANNEL:=stable}"
  ACCESS_TOKEN_CHECK="${ATOM_ACCESS_TOKEN:=unset}"
  if [ "$ACCESS_TOKEN_CHECK" = "unset" ]; then
    export ATOM_ACCESS_TOKEN="da809a6077bb1b0aa7c5623f7b2d5f1fec2faae4"
  fi

  if [ "$TRAVIS_OS_NAME" = "osx" ]; then
      curl -s -L "https://atom.io/download/mac?channel=$ATOM_CHANNEL" \
        -H 'Accept: application/octet-stream' \
        -o "atom.zip"
      mkdir atom
      unzip -q atom.zip -d atom
      if [ "$ATOM_CHANNEL" = "stable" ]; then
        export ATOM_APP_NAME="Atom.app"
        export ATOM_SCRIPT_NAME="atom.sh"
        export ATOM_SCRIPT_PATH="./atom/${ATOM_APP_NAME}/Contents/Resources/app/atom.sh"
      else
        export ATOM_APP_NAME="Atom ${ATOM_CHANNEL}.app"
        export ATOM_SCRIPT_NAME="atom-${ATOM_CHANNEL}"
        export ATOM_SCRIPT_PATH="./atom-${ATOM_CHANNEL}"
        ln -s "./atom/${ATOM_APP_NAME}/Contents/Resources/app/atom.sh" "${ATOM_SCRIPT_PATH}"
      fi
      export ATOM_PATH="./atom"
      export APM_SCRIPT_PATH="./atom/${ATOM_APP_NAME}/Contents/Resources/app/apm/node_modules/.bin/apm"
  else
      curl -s -L "https://atom.io/download/deb?channel=$ATOM_CHANNEL" \
        -H 'Accept: application/octet-stream' \
        -o "atom.deb"
      /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16
      export DISPLAY=":99"
      dpkg-deb -x atom.deb "$HOME/atom"
      if [ "$ATOM_CHANNEL" = "stable" ]; then
        export ATOM_SCRIPT_NAME="atom"
        export APM_SCRIPT_NAME="apm"
      else
        export ATOM_SCRIPT_NAME="atom-$ATOM_CHANNEL"
        export APM_SCRIPT_NAME="apm-$ATOM_CHANNEL"
      fi
      export ATOM_SCRIPT_PATH="$HOME/atom/usr/bin/$ATOM_SCRIPT_NAME"
      export APM_SCRIPT_PATH="$HOME/atom/usr/bin/$APM_SCRIPT_NAME"
  fi

  echo "Using Atom version:"
  "$ATOM_SCRIPT_PATH" --version
  echo "Using apm version:"
  "$APM_SCRIPT_PATH" --version
  echo "Using node version:"
  node --version
  echo "Using npm version:"
  npm --version

  echo "Downloading package dependencies..."
  "$APM_SCRIPT_PATH" install

  echo "Running lint..."
  npm run lint
  LINT_RESULT=$?
  if [ $LINT_RESULT -ne 0 ]; then echo ">>> LINTING FAILED! <<< Continuing on to tests..."; fi

  echo "Running specs..."
  "$ATOM_SCRIPT_PATH" --test test
  TEST_RESULT=$?

  echo "=================="
  echo "Linting exit code: $LINT_RESULT"
  echo "Test exit code: $TEST_RESULT"
  if [ $LINT_RESULT -ne 0 ]; then exit $LINT_RESULT; fi
  if [ $TEST_RESULT -ne 0 ]; then exit $TEST_RESULT; fi
  exit
}

if [ "$TRAVIS_BUILD_JOB" = "schemacheck" ]
then
  checkForSchemaChanges
else
  runTests
fi
