#!/bin/bash

# create_environment - A script to deploy AWS resources for asset ingestion

function usage
{
  echo "usage: create_environment.sh [[-i] | [-e environment] [-r region] [-a account] [-p profilename]"
}

INTERACTIVE=
ENVIRONMENT=
REGION=
ACCOUNT=
PROFILE_NAME=

while [ "$1" != "" ]; do
    case $1 in
        -e | --environment )    shift
                                ENVIRONMENT=$1
                                ;;
        -r | --region )         shift
                                REGION=$1
                                ;;
        -a | --account )        shift
                                ACCOUNT=$1
                                ;;
        -p | --profilename )    shift
                                PROFILE_NAME=$1
                                ;;
        -i | --interactive )    INTERACTIVE=1
                                ;;
        -h | --help )           usage
                                exit
                                ;;
        * )                     usage
                                exit 1
    esac
    shift
done

if [ "$INTERACTIVE" = "1" ]; then
  echo "Specify the environment (dev, qa, prod), followed by [ENTER]:"
  read ENVIRONMENT

  echo "Specify region, followed by [ENTER]:"
  read REGION

  echo "Specify AWS account number (without dashes), followed by [ENTER]:"
  read ACCOUNT

  echo "Specify AWS creds profile name, followed by [ENTER]:"
  read PROFILE_NAME
else
  if [ "$ENVIRONMENT" == "" ] ||
      [ "$REGION" == "" ] ||
      [ "$ACCOUNT" == "" ] ||
      [ "$PROFILE_NAME" == "" ] ; then
    usage
    exit 1
  fi
fi
RAW_ASSETS="$ENVIRONMENT-raw-assets"
LOG_RAW_ASSETS="logRawAssetToDynamoDB"

echo "Packaging the Lambda function code"
zip -r "$LOG_RAW_ASSETS.zip" "$LOG_RAW_ASSETS.js"

# This function is idempotent
echo "Creating requisite S3 bucket: $RAW_ASSETS"
aws s3 mb "s3://$RAW_ASSETS" \
--region "$REGION" \
--profile "$PROFILE_NAME"

# This function is idempotent
echo "Creating SNS topic: $RAW_ASSETS"
aws sns create-topic \
--name "$RAW_ASSETS" \
--profile "$PROFILE_NAME"

# This function is idempotent
echo "Setting SNS topic policy to allow S3 bucket events"
aws sns set-topic-attributes \
--topic-arn "arn:aws:sns:$REGION:$ACCOUNT:$RAW_ASSETS" \
--attribute-name Policy \
--attribute-value "{
  \"Version\": \"2008-10-17\",
  \"Id\": \"__default_policy_ID\",
  \"Statement\": [
    {
      \"Sid\": \"__default_statement_ID\",
      \"Effect\": \"Allow\",
      \"Principal\": {
        \"AWS\": \"*\"
      },
      \"Action\": [
        \"SNS:Subscribe\",
        \"SNS:ListSubscriptionsByTopic\",
        \"SNS:DeleteTopic\",
        \"SNS:GetTopicAttributes\",
        \"SNS:Publish\",
        \"SNS:RemovePermission\",
        \"SNS:AddPermission\",
        \"SNS:Receive\",
        \"SNS:SetTopicAttributes\"
      ],
      \"Resource\": \"arn:aws:sns:$REGION:$ACCOUNT:$RAW_ASSETS\",
      \"Condition\": {
        \"ArnEquals\": {
          \"aws:SourceArn\": \"arn:aws:s3:::$RAW_ASSETS\"
        }
      }
    }
  ]
}" \
--profile "$PROFILE_NAME"

# This function is idempotent
echo "Creating S3 bucket notification on SNS topic whenever an object is created"
aws s3api put-bucket-notification-configuration \
--bucket "$RAW_ASSETS" \
--notification-configuration "{
  \"TopicConfigurations\": [
      {
          \"TopicArn\": \"arn:aws:sns:$REGION:$ACCOUNT:$RAW_ASSETS\",
          \"Events\": [
              \"s3:ObjectCreated:*\"
          ]
      }
  ]
}" \
--profile "$PROFILE_NAME"

echo "Checking if DynamoDB table already exists: $RAW_ASSETS"
description=$(aws dynamodb describe-table \
  --table-name "$RAW_ASSETS" \
  --profile "$PROFILE_NAME")
if [[ "$description" == *"ResourceNotFoundException"* ]]
then
  echo "Creating DynamoDB table for logging raw assets: $RAW_ASSETS"
  aws dynamodb create-table \
  --attribute-definitions AttributeName=upc,AttributeType=S AttributeName=trackid,AttributeType=S \
  --table-name "$RAW_ASSETS" \
  --key-schema AttributeName=upc,KeyType=HASH AttributeName=trackid,KeyType=RANGE \
  --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
  --profile "$PROFILE_NAME"
else
  echo "DynamoDB table already exists - here is its configuration:"
  echo "$description"
fi

echo "Checking if Lambda function already exists: $ENVIRONMENT-$LOG_RAW_ASSETS"
description=$(aws lambda get-function \
  --function-name "$ENVIRONMENT-$LOG_RAW_ASSETS" \
  --profile "$PROFILE_NAME")
if [[ "$description" == *"ResourceNotFoundException"* ]]
then
  echo "Creating Lambda function: $ENVIRONMENT-$LOG_RAW_ASSETS"
  aws lambda create-function \
  --region "$REGION" \
  --function-name "$ENVIRONMENT-$LOG_RAW_ASSETS" \
  --zip-file "fileb://$PWD/$LOG_RAW_ASSETS.zip" \
  --role "arn:aws:iam::$ACCOUNT:role/$ENVIRONMENT-lambda_dynamo" \
  --handler "$LOG_RAW_ASSETS.handler" \
  --runtime nodejs \
  --memory-size 128 \
  --timeout 10 \
  --profile "$PROFILE_NAME"
else
  echo "Lambda function already exists - here is its configuration:"
  echo "$description"
  echo "Publishing Lambda function code"
  aws lambda update-function-code \
  --function-name "$ENVIRONMENT-$LOG_RAW_ASSETS" \
  --zip-file "fileb://$PWD/$LOG_RAW_ASSETS.zip" \
  --publish \
  --profile "$PROFILE_NAME"
fi

# This function is idempotent
echo "Subscribing Lambda function to SNS endpoint"
aws sns subscribe \
--topic-arn "arn:aws:sns:$REGION:$ACCOUNT:$RAW_ASSETS" \
--protocol lambda \
--notification-endpoint "arn:aws:lambda:$REGION:$ACCOUNT:function:$ENVIRONMENT-$LOG_RAW_ASSETS" \
--profile "$PROFILE_NAME"
