#!/bin/bash -e
COPYRIGHT='#
# Copyright (c) 2017 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
'

name="${1:-$(basename "$(dirname "$(dirname "$PWD")")")}"

defs="variables.tf"
inputs=( )
simple_inputs=( )
list_inputs=( )

locals=

contains()
{
  local i
  local e="$1"
  shift
  for i; do
    if [ "$i" == "$e" ]; then
      return 0
    fi
  done
  return 1
}

print_default()
{
  local d="${defaults[$1]}"
  if [ -n "$d" ]; then
    echo "default = \"\${module.$d.value}\""
  fi
}

print_locals()
{
  cat <<EOF
#
# [] operator only supports homogeneous maps in terraform
# so we have to separate list from simple config values in two separate sub maps
# but [] supports nested maps (but not the lookup function)
# Therefore we cannot use a defaulted lookup, but have to be assure the entry exists.
#
locals {
  struct = {
    simple = {}
    list = {}
  }
  config = "\${merge(local.struct,var.iaas_config)}"
  simple = "\${local.config["simple"]}"
  list = "\${local.config["list"]}"
}
EOF
  if [ -n "$locals" ]; then
    echo "locals {"
    for l in "${simple_inputs[@]}"; do
      echo "  $l = \"\${lookup(local.config,\"$l\",var.$l)}\""
    done
    echo "}"
  else
    for l in "${simple_inputs[@]}"; do
      cat <<EOF
module "$l" {
  source="../../../../modules/variable"
  value="\${lookup(local.simple,"$l",var.$l)}"
  $(print_default $l)
}
EOF
    done
    for l in "${list_inputs[@]}"; do
      cat <<EOF
module "$l" {
  source="../../../../modules/lookup_list"
  map = "\${local.list}"
  key = "$l"
  default = "\${var.$l}"
}
EOF
    done
  fi
}

lvalue()
{
  if [ -n "$locals" ]; then
    echo -n "\"\${local.$1}\""
  else
    echo -n "\"\${module.$1.value}\""
  fi
}

print_simple_args()
{
  print_args "${simple_inputs[@]}"
}
print_list_args()
{
  print_args "${list_inputs[@]}"
}

print_args()
{
  for l in "$@"; do
    echo "      $l = $(lvalue $l)"
  done
}

print_outputs()
{
  for l in "${inputs[@]}"; do
    cat <<EOF
output "$l" {
  value = $(lvalue $l)
}
EOF
  done
}

get_variables()
{
  for v in $defs; do
    (
      V=
      D=
      T=string
      while read a; do
        n="$(grep "variable[[:space:]]" <<< "$a" | sed -e 's/.*"\(.*\)".*/\1/')"
        if [ -n "$n" ]; then
          if [ -n "$V" ]; then
            echo "$V $T $D"
          fi
          echo VAR $n >&2
          V="$n"
          T=string
          d="$(grep "# default:" <<< "$a" | sed -e 's/.*# default:\(.*\)/\1/')"
          if [ -n "$d" ]; then
            echo DEF $d >&2
            D="$d"
          else
            D=
          fi
        else
          t="$(grep "type[[:space:]]=" <<< "$a" | sed -e 's/.*"\(.*\)".*/\1/')"
          if [ -n "$t" ]; then
            T="$t"
          fi
        fi
      done
      if [ -n "$V" ]; then
        echo "$V $T $D"
      fi
    ) < "$v"
  done

}

declare -A defaults

for v in $defs; do
  while read n t d; do
    case "$t" in
      string) simple_inputs+=( $n );;
      list) list_inputs+=( $n );;
      *) echo "invalid variable type '$t' for $n" >&1
         exit 1;;
    esac
    if [ -n "$d" ]; then
       defaults[$n]="$d"
    fi
  done <<<"$(get_variables)"
done

inputs=( "${simple_inputs[@]}" "${list_inputs[@]}" )

cat >config.tf <<EOF
$COPYRIGHT
##############################################################################
# $name iaas configuration handling
# pack or unpack configuration variables for iaas layer
# generated by create.sh based on variables.tf
##############################################################################

#
# specify config map to unpack settings into output
#
variable "iaas_config" {
  type = "map"
  default = { }
}

#
# or specify variables according to variables.tf to
# pack a config map
#

$(print_locals)

#
# always provide a config map value
#
locals {
  iaas_config = {
    simple = {
$(print_simple_args)
    }
    list = {
$(print_list_args)
    }
  }
}

output "iaas_config" {
  value = "\${local.iaas_config}"
}

output "simple" {
  value = {
$(print_simple_args)
  }
}
output "list" {
  value = {
$(print_list_args)
  }
}

#
# always provide all settings as dedicated output
#
$(print_outputs)
EOF
