#!/bin/sh
set -e
# Regions where AWS Lambda + API Gateway are available
regions=( eu-central-1 eu-west-1 us-west-2 us-east-1 ap-northeast-1 ap-southeast-2 )
# Valid npm version arguments
npmActions=( patch minor major )
# Local path to the CFN template file
templatePath="_scripts"
# Template file name
templateName="ApiGatewayCloudFormation.template"
# S3 bucket name prefix (.{region} is appended to the name)
s3BucketName="apigatewaycloudformation"
# Source file name
sourceFileName="source.zip"

version=""
while getopts ":a:v:" opt; do
  case ${opt} in
    v)
        version="${OPTARG}"
    ;;
    \?)
        echo "Invalid argument: -$OPTARG" >&2
        usage
    ;;
  esac
done

# Parse version from version string.
# Will run npm version methods if version is not provided or one of patch, minor or major.
# All other values will be used as is but prefixed by test/.
function parseVersion() {
    if [[ " ${npmActions[@]} " =~ " ${1} " ]]; then
        npmVersionCommand=${1}
    fi

    if [ "${npmVersionCommand}" != "" ]; then
        version=$(npm version ${npmVersionCommand})
        if [ -z ${version} ]; then
            exit 1;
        fi
        version=${version:1}
    else
        version=test/${1}
    fi

    echo ${version}
}

# Packages the source code to a zip file (${sourceFileName})
function package() {
    npm prune --production
    zip -r source.zip lib/* lib/*/** node_modules/*/** > /dev/null 2>&1
}

# Publishes the source file and CFN template to S3.
# It will publish to all ${regions}. If the bucket does not exist it is created.
# If version matches *test/* it's only uploaded to eu-west-1. These versions are only available to 10 days,
function publish() {
    echo "Publishing version: ${version}"

    if [[ " ${version} " != *"test/"* ]]; then
        sed -i '.original' "s/{VERSION}/${version}/g" ${templatePath}/${templateName}
        for region in "${regions[@]}"; do
            sed -i '.version' "s/{REGION}/${region}/g" ${templatePath}/${templateName}
            bucketName="${s3BucketName}.${region}"
            aws s3api head-bucket --bucket ${bucketName} --region ${region}

            if [ $? -ne 0 ]; then
                if [ "${region}" == "us-east-1" ]; then
                    aws s3api create-bucket --bucket ${bucketName} --region ${region}
                else
                    aws s3api create-bucket --bucket ${bucketName} --region ${region} --create-bucket-configuration LocationConstraint=${region}
                fi
                sleep 3
                aws s3api put-bucket-policy --bucket ${bucketName} --region ${region} --policy "{ \"Statement\": [ { \"Effect\": \"Allow\", \"Principal\": \"*\", \"Action\": \"s3:GetObject\", \"Resource\": \"arn:aws:s3:::${bucketName}/*\" } ] }"
            fi

            aws s3 cp ${sourceFileName} s3://${bucketName}/${version}/${sourceFileName} --region ${region}
            aws s3 cp ${templatePath}/${templateName} s3://${bucketName}/${version}/${templateName} --region ${region}
            echo "* <a href=\"https://s3.amazonaws.com/${bucketName}/${version}/${templateName}\">${region} template</a>"

            rm -f ${templatePath}/${templateName}
            mv ${templatePath}/${templateName}.version ${templatePath}/${templateName}
        done
    else
        sed -i '.original' "s:{VERSION}:${version}:g" ${templatePath}/${templateName}
        sed -i '.version' "s/{REGION}/eu-west-1/g" ${templatePath}/${templateName}
        aws s3 cp ${sourceFileName} s3://${s3BucketName}.eu-west-1/${version}/${sourceFileName} --region eu-west-1
        aws s3 cp ${templatePath}/${templateName} s3://${s3BucketName}.eu-west-1/${version}/${templateName} --region eu-west-1
        aws s3 cp ${sourceFileName} s3://${s3BucketName}.us-east-1/${version}/${sourceFileName} --region us-east-1
        aws s3 cp ${templatePath}/${templateName} s3://${s3BucketName}.us-east-1/${version}/${templateName} --region us-east-1
        echo "https://s3.amazonaws.com/${s3BucketName}.eu-west-1/${version}/${templateName}"
        rm -f ${templatePath}/${templateName}.version
    fi

    rm -f ${sourceFileName}
    rm -f ${templatePath}/${templateName}
    mv ${templatePath}/${templateName}.original ${templatePath}/${templateName}
    echo "Version ${version} published to AWS"
}

function usage() {
    echo "Usage: publish.sh -v version"
    echo "-v patch|minor|major will publish a new npm version, any other value will be used as is."
    exit 1;
}

if [[ -z "${version}" ]]; then
    usage
fi

version=$(parseVersion ${version}) || exit 1;
package || exit 1;
publish ${version}

if [[ " ${version} " != *"test/"* ]]; then
    git push --tags
fi
