#!/bin/bash

# Minimal version for OC
OC_MIN_VERSION=3.9.0

# Constant for signal to configure oc via minishift
SETUP_MINISHIFT="setup-minishift"

check_oc_version()
{
    local minimum=${OC_MIN_VERSION}
    #
    # Removes any lines containing kubernetes or server
    # Extracts any version number of the format dd.dd.dd, eg. 3.10.0 or 4.1.0
    #
    set_gnugrep

    local test=$(oc version | $gnugrep -Eiv 'kubernetes|server' | $gnugrep -o '[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\?')

    if [ -z "$test" ]; then
      echo "ERROR: 'Version of oc could not be found'"
      return
    fi

    echo $(compare_version $test $minimum)
}

is_minishift_available() {
    # Check for minishift
    set +e
    which minishift &>/dev/null
    if [ $? -ne 0 ]; then
        set -e
        echo "ERROR: 'minishift is not installed so cannot use for 'oc'"
        return
    fi

    local running=$(minishift status | grep Minishift | sed 's/Minishift:\( \)*//g')
    if [ "$running" != "Running" ]; then
      echo "ERROR: minishift is not running"
      return
    fi

    echo "OK"
}

setup_oc() {

    # Check path first if it already exists
    set +e
    which oc &>/dev/null
    if [ $? -eq 0 ]; then
      set -e
      err=$(check_oc_version)
      check_error $err
      return
    fi

    # Check for minishift
    hasminishift=$(is_minishift_available)
    if [ "$hasminishift" == "OK" ]; then
      set -e
      eval $(minishift oc-env)
      err=$(check_oc_version)
      check_error $err
      return
    fi

    set -e

    # Error, no oc found
    echo "ERROR: No 'oc' binary found in path. Please install the client tools from https://github.com/openshift/origin/releases/tag/v3.9.0 (or newer)"
    exit 1
}

setup_minishift_oc() {
   eval $(minishift oc-env)
   echo $(check_oc_version)
}

#
# Same as setup_oc but doesn't exit
# if oc not found
#
is_oc_available() {

    # Check path first if it already exists
    set +e
    which oc &>/dev/null
    if [ $? -eq 0 ]; then
      set -e
      echo $(check_oc_version)
      return
    fi

    #
    # Check for minishift
    #
    # Will return $SETUP_MINISHIFT as the result since
    # this will signal the parent shell should call setup_minishift_oc.
    # This cannot be called here since this will be called from a child
    # shell and so the changes to the PATH variable will not be propogated
    # to the parent shell.
    #
    hasminishift=$(is_minishift_available)
    if [ "$hasminishift" == "OK" ]; then
      set -e
      echo "$SETUP_MINISHIFT"
      return
    fi

    set -e

    # Error, no oc found
    echo "ERROR: No 'oc' binary found in path. Please install the client tools from https://github.com/openshift/origin/releases/tag/v3.9.0 (or newer)"
}

recreate_project() {
    local project=$1
    local dont_ask=${2:-false}

    if [ -z "$project" ]; then
        echo "No project given"
        exit 1
    fi

    # Delete project if existing
    if oc get project "${project}" >/dev/null 2>&1 ; then
        if [ $dont_ask != "true" ]; then
            echo =============== WARNING -- Going to delete project ${project}
            oc get all -n $project
            echo ============================================================
            read -p "Do you really want to delete the existing project $project ? yes/[no] : " choice
            echo
            if [ "$choice" != "yes" ] && [ "$choice" != "y" ]; then
                echo "Aborting on user's request"
                exit 1
            fi
        fi
        echo "Deleting project ${project}"
        oc delete project "${project}"
    fi

    # Create project afresh
    echo "Creating project ${project}"
    for i in {1..10}; do
        if oc new-project "${project}" >/dev/null 2>&1 ; then
            break
        fi
        echo "Project still exists. Sleeping 10s ..."
        sleep 10
    done
    oc project "${project}"
}

# Install maven mirror
install_maven_mirror() {
    local project=$(oc project --short=true)
    recreate_project "nexus"

    oc new-app sonatype/nexus >/dev/null 2>&1
    oc expose svc/nexus >/dev/null 2>&1

    oc set probe dc/nexus \
        --liveness \
        --failure-threshold 3 \
        --initial-delay-seconds 30 \
        -- echo ok >/dev/null 2>&1
	oc set probe dc/nexus \
        --readiness \
        --failure-threshold 3 \
        --initial-delay-seconds 30 \
        --get-url=http://:8081/nexus/content/groups/public >/dev/null 2>&1
    oc set volume dc/nexus --add \
        --name 'nexus-volume-1' \
        --type 'pvc' \
        --mount-path '/sonatype-work/' \
        --claim-name 'nexus-pv' \
        --claim-size '2G' \
        --overwrite >/dev/null 2>&1

    wait_for_deployments 1 nexus

    nexus_host=$(oc get routes nexus -o=jsonpath='{.spec.host}')

    echo "Setting up redhat-ga and atlassian proxy..."

    curl -X POST \
        http://${nexus_host}/nexus/service/local/repositories \
        -H 'authorization: Basic YWRtaW46YWRtaW4xMjM=' \
        -H 'cache-control: no-cache' \
        -H 'content-type: application/json' \
        -d '{"data":{"repoType":"proxy","id":"redhat-ga","name":"Red Hat General Availability Repository","browseable":true,"indexable":true,
        "notFoundCacheTTL":1440,"artifactMaxAge":-1,"metadataMaxAge":1440,"itemMaxAge":1440,"repoPolicy":"RELEASE",
        "provider":"maven2","providerRole":"org.sonatype.nexus.proxy.repository.Repository","downloadRemoteIndexes":true,
        "autoBlockActive":true,"fileTypeValidation":true,"exposed":true,"checksumPolicy":"WARN",
        "remoteStorage":{"remoteStorageUrl":"https://maven.repository.redhat.com/ga/","authentication":null,
        "connectionSettings":null}}}' \
        >/dev/null 2>&1

    curl -X POST \
        http://${nexus_host}/nexus/service/local/repositories \
        -H 'authorization: Basic YWRtaW46YWRtaW4xMjM=' \
        -H 'cache-control: no-cache' \
        -H 'content-type: application/json' \
        -d '{"data":{"repoType":"proxy","id":"atlassian-public","name":"Atlassian Public","browseable":true,"indexable":true,
        "notFoundCacheTTL":1440,"artifactMaxAge":-1,"metadataMaxAge":1440,"itemMaxAge":1440,"repoPolicy":"RELEASE",
        "provider":"maven2","providerRole":"org.sonatype.nexus.proxy.repository.Repository","downloadRemoteIndexes":true,
        "autoBlockActive":true,"fileTypeValidation":true,"exposed":true,"checksumPolicy":"WARN",
        "remoteStorage":{"remoteStorageUrl":"https://packages.atlassian.com/maven-external","authentication":null,
        "connectionSettings":null}}}' \
        >/dev/null 2>&1

    curl -X PUT \
        http://${nexus_host}/nexus/service/local/repo_groups/public \
        -H 'authorization: Basic YWRtaW46YWRtaW4xMjM=' \
        -H 'cache-control: no-cache' \
        -H 'content-type: application/json' \
        -H 'postman-token: eaa6b07c-87ac-53c5-1ab6-aa585ae9ee3c' \
        -d '{"data":{"id":"public","name":"Public Repositories","format":"maven2","exposed":true,"provider":"maven2",
        "repositories":[{"id":"releases"},{"id":"snapshots"},{"id":"thirdparty"},{"id":"central"},
        {"id":"redhat-ga"},{"id":"atlassian-public"}]}}' \
        >/dev/null 2>&1

    oc project "${project}"

    echo "Optionally set MAVEN_MIRROR_URL with:"
    echo "export MAVEN_MIRROR_URL=\"http://${nexus_host}/nexus/content/groups/public/\""
}

# Determine maven mirror url
maven_mirror_url() {
    local maven_mirror="${MAVEN_MIRROR_URL:-unknown}"
    if [ "${maven_mirror}" == "unknown" ]; then
        project=$(oc project --short=true)
        if oc get project "nexus" >/dev/null 2>&1 ; then
            oc project "nexus" >/dev/null 2>&1
            nexus_host=$(oc get routes nexus -o=jsonpath='{.spec.host}')
            oc project "${project}" >/dev/null 2>&1
            echo "http://${nexus_host}/nexus/content/groups/public/"
            return
        fi
        echo "ERROR: Could not automatically determine MAVEN_MIRROR_URL, please make sure you run "
        echo "'syndesis crc --install --maven-mirror' or 'syndesis dev --install-maven-mirror' or setup maven nexus project manually."
        return
    fi
    echo "${maven_mirror}"
}

create_openshift_resource() {
    create_or_delete_openshift_resource "create" "${1:-}" "${2:-}"
}

delete_openshift_resource() {
    create_or_delete_openshift_resource "delete --ignore-not-found" "${1:-}" "${2:-}"
}

create_or_delete_openshift_resource() {
    local what=${1}
    local resource=${2:-}
    local parameters=${3:-}
    local tag="$(readopt --tag)"
    local use_local_resource="$(hasflag --local)"

    local result

    set +e
    if [ -n "$use_local_resource" ]; then
        local template="tee"
        if [ -n "$parameters" ]; then
          template="oc process -f - -p $parameters"
        fi

        if [ -n "$tag" ]; then
            pushd $(appdir) >/dev/null
            git fetch --tags
            result=$(git show $tag:${resource} | $template | oc $what -f - >$ERROR_FILE 2>&1)
            if [ $? -ne 0 ]; then
                echo "ERROR: Cannot create $resource (tag: $tag)"
            fi
            popd >/dev/null
        else
            result=$(cat $(appdir)/../$resource | $template | oc $what -f - >$ERROR_FILE 2>&1)
            if [ $? -ne 0 ]; then
                echo "ERROR: Cannot create local $(appdir)/../$resource"
            fi
        fi
    else
        local url="https://raw.githubusercontent.com/syndesisio/syndesis/${tag:-$(curl -s https://api.github.com/repos/syndesisio/syndesis |jq -r .default_branch)}/${resource}"

        if [ -z "$parameters" ]; then
            result=$(oc $what -f $url >$ERROR_FILE 2>&1)
        else
            result=$(oc process -f $url -p $parameters | oc $what -f - >$ERROR_FILE 2>&1)
        fi
        if [ $? -ne 0 ]; then
            echo "ERROR: Cannot create remote resource $url"
        fi
    fi
    set -e
}

scale_deployments() {
  local replicas=$1
  shift
  local dcs="$@"
  for dc in $dcs; do
    oc scale dc $dc --replicas=$replicas
  done
  wait_for_deployments $replicas $dcs
}

wait_for_deployments() {
  local replicas_desired=$1
  shift
  local dcs="$@"

  oc get pods -w &
  watch_pid=$!
  for dc in $dcs; do
      echo "Waiting for $dc to be scaled to ${replicas_desired}"
      local replicas=$(get_replicas $dc)
      while [ -z "$replicas" ] || [ "$replicas" -ne $replicas_desired ]; do
          echo "Waiting for $dcs - Sleeping 10s ..."
          sleep 10
          replicas=$(get_replicas $dc)
      done
  done
  kill $watch_pid
}

get_replicas() {
  local dc=${1}
  local hasDc=$(oc get deployment -o name | grep $dc)
  if [ -z "$hasDc" ]; then
      echo "0"
      return
  fi
  oc get deployment $dc -o jsonpath="{.status.availableReplicas}"
}

pod() {
  local dc=${1}
  local ret=$(oc get pod -o name | grep "$dc" | sed -e "s/^pods\///")
  local nr_pods=$(echo $ret | wc -l | awk '$1=$1')
  if [ $nr_pods != "1" ]; then
      echo "ERROR: More than 1 pod found for $dc ($nr_pods found)"
  fi
  echo $ret
}

get_route() {
  local name="${1}"
  oc get route $name -o jsonpath="{.spec.host}"
}

syndesis_deployments() {
  oc get dc -l syndesis.io/app=syndesis -o name | sed -e "s/^deploymentconfigs\///"
}
