#!/usr/bin/env bash
# ==============================================================================
# Proprietary License -- All Rights Reserved
#
# Copyright (c) 2017 Dealerdirect B.V.
# ==============================================================================

set -o errexit  # Exit script when a command exits with non-zero status.
set -o errtrace # Exit on error inside any functions or sub-shells.
set -o nounset  # Exit script on use of an undefined variable.
set -o pipefail # Return exit status of the last command in the


readonly EX_OK=0 # Successful termination
readonly EX_DEPENDENCY_MISSING=66 # A dependency could not be found
readonly EX_COULD_NOT_DOWNLOAD=67 # Could not download the swagger-codegen-cli JAR file
readonly EX_COULD_NOT_GENERATE=68 # The swagger-codegen-cli encountered an error while generating

readonly g_sProjectRoot="$( cd "$( dirname "$( dirname "${BASH_SOURCE[0]}" )" )" && pwd )"
readonly g_sSwaggerJarFile="${PWD}/bin/swagger-codegen-cli.jar"
readonly g_sSwaggerJarUrl='http://central.maven.org/maven2/io/swagger/swagger-codegen-cli/2.2.2/swagger-codegen-cli-2.2.2.jar'

isInstalled() {
    # shellcheck disable=SC2046
    return $(command -v "${1}" >/dev/null 2>&1);
}

printError() {
  echo
  echo " !     ERROR: $*" 1>&2
  echo
}

printStatus() {
    echo "-----> $*"
}

printTopic() {
    echo
    echo "=====> $*"
}

validate_sed() {
    case $(sed --help 2>&1) in
      *GNU*) printStatus 'GNU-sed found';;
      *) printError "Could not find 'GNU-sed'. Aborting.";exit ${EX_DEPENDENCY_MISSING};;
    esac
}

validate_dependencies() {
    local sDependency

    printTopic 'Validating dependencies...'

    for sDependency in "${@}"; do
        validate_dependency "${sDependency}"
    done
}

validate_dependency() {

    local -r sSubject="${1}"

    printStatus "Checking ${sSubject} is available..."

    if ! isInstalled "${sSubject}";then
        printError "Could not find '${sSubject}'. Aborting."
        exit ${EX_DEPENDENCY_MISSING}
    fi
}

validate_swagger_jar() {
    printTopic 'Checking Swagger Generator is available...'

    if [[  -f "${g_sSwaggerJarFile}" ]];then
        printStatus 'Swagger JAR file found'
    else
        printStatus 'Could not find Swagger JAR file'
        printStatus "Downloading from '${g_sSwaggerJarUrl}'"

        wget "${g_sSwaggerJarUrl}" -O "${g_sSwaggerJarFile}" || (
            printError 'Download failed. Aborting.'
            exit ${EX_COULD_NOT_DOWNLOAD}
        )
    fi
}

composer_install() {
    printTopic 'Making sure all PHP dependencies are installed'
    composer install
}

pre_generate() {

    validate_dependencies 'java' 'php' 'composer' 'sed' 'wget'

    validate_sed

    validate_swagger_jar

    composer_install
}

clean_up_composer() {
    printStatus 'Cleaning up composer.json'

    # Search and replacement patterns, separated by a single pipe "|" character
    declare -a -r aReplace=(
        '"description": "",|"description": "Client to communicate with the Dealerdirect Email Service.",'
    )

    for sPattern in "${aReplace[@]}"; do
        sed -i "s|$sPattern|g" "${g_sProjectRoot}/composer.json"
    done
}

clean_up_readme() {

    printStatus 'Cleaning up README file'
    # Search and replacement patterns, separated by a single pipe "|" character
    # shellcheck disable=SC2016
    declare -a -r aReplace=(
        '^## Author$|'
        '^# $|# Dealerdirect Email Service SDK\n'
        '^### Composer$|\n### Composer'
        'Then run `composer install`|Then run `composer require dealerdirect/email-service-sdk`'
        'https://github.com/dealerdirect/email-service-sdk.git|git@git.dealerdirect.io:php-packages/email-service-sdk.git'
        '^  ],$|  ]'
        '^  }$|'
        '^  \"require\": {$|'
        '^    "dealerdirect/email-service-sdk": "\*@dev"$|'
        '^## Installation & Usage|## Installation \& Usage\n\n\n\n_**For documentation on generating a new SDK see [here](./docs/generating-sdk.md).**_'
    )

    for sPattern in "${aReplace[@]}"; do
        sed -i "s|$sPattern|g" "${g_sProjectRoot}/README.md"
    done

    # Remove multiple empty lines
    sed -i '/^$/N;/\n$/D' "${g_sProjectRoot}/README.md"
}

remove_files() {

    local sFile

    printTopic 'Removing unwanted files'

    for sFile in "${@}"; do
        remove_file "${sFile}"
    done
}

remove_file() {
    local -r sFile="${1}"

    printStatus "Removing ${sFile}"

    rm -f "${g_sProjectRoot:?}/${sFile}"
}

clean_up_code() {
    printStatus 'Cleaning up code'
    # Because the fixer given an error code on success we just ignore this piece of crap.
    php "${g_sProjectRoot}/vendor/bin/php-cs-fixer" 'fix' || true
}

post_generate() {
    printTopic 'Cleaning up...'

    clean_up_readme
    clean_up_composer
    clean_up_code

    remove_files '.travis.yml' '.swagger-codegen-ignore' '.php_cs' '.php_cs.cache' 'git_push.sh'
}

generate() {
    printTopic 'Generating SDK'

    printStatus 'Generating PHP files'
    java -jar "${g_sSwaggerJarFile}" generate \
        --input-spec "${g_sProjectRoot}/swagger.json" \
        --lang 'php' \
        --output "${g_sProjectRoot}/" \
        --config "${g_sProjectRoot}/config.json" || (
            printError 'Could not generate SDK'
            exit ${EX_COULD_NOT_GENERATE}
        )

}

generate_email_service_sdk() {

    pre_generate

    generate

    post_generate

    echo 'Done.'

    exit ${EX_OK}
}

if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
    # direct call to file
    generate_email_service_sdk
fi  # else file is included from another script

#EOF
