#!/bin/bash

# Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved.
# 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.

set -euo pipefail

if [ "$(id -un)" != "openlkadmin" ]
then
    echo "unexpected user"
    exit 1
fi
echo "starting hetu process"

CONFIG_PATH='/usr/lib/hetu/etc'

if [[ ! -d "$CONFIG_PATH" ]]; then
    ln -s /usr/lib/hetu/default/etc /usr/lib/hetu/etc
fi
if [[ ! -d /etc/hetu/catalog ]]; then
    if [[ -d "$CONFIG_PATH"/catalog ]]; then
        ln -s $CONFIG_PATH/catalog /etc/hetu/catalog
    fi
fi
if [[ ! -d /usr/lib/hetu/lib/plugin ]]; then
    if [[ -d /usr/lib/hetu/plugin ]]; then
        ln -s /usr/lib/hetu/plugin /usr/lib/hetu/lib/plugin
    fi
fi

setConfig() {
    local i=0
    unset attributes
    declare -a attributes
    while read line || [[ -n "$line" ]]; do
       attributes[$((i++))]=$line
    done < $1
    numPattern=${#patterns[@]}
    # add new patterns directly
    for ((i=0; i<$numPattern; i++)); do
        exists=0
        for ((k=0; k<${#attributes[@]}; k++)); do
             if [[ ${attributes[$k]} =~ ^${patterns[$i]}.* ]]; then
                exists=1
                break;
             fi
        done
        if [ $exists == 0 ]; then
            attributes+=( "${patterns[$i]}" )
        fi
    done
    touch "$1.tmp"
    chmod --reference="$1" "$1.tmp"
    for ((i=0; i<${#attributes[@]}; i++)); do
        for ((k=0; k<$numPattern; k++)); do
            attributes[$i]=$(echo ${attributes[$i]}| sed -e "s|${patterns[$k]}|${values[$k]}|m")
        done
        if [ "" != "${attributes[$i]}" ]; then
            echo "${attributes[$i]}" >> "$1.tmp"
        fi
    done
    mv "$1"{.tmp,}
    unset patterns
    unset values
}

updateConfigByFile() {
    local thisConfig="$1"
    local thatConfig="$2"
    local numAttri=0

    unset attributes
    declare -a attributes
    while read line || [[ -n "$line" ]]; do
        attributes[$((numAttri++))]=$line
    done < ${thisConfig}

    declare -a patterns
    declare -a values
    local i=0
    # discard any empty line;
    while read line || [[ -n "$line" ]]; do
        if [[ -n "$line" ]]; then
            if [[ ${line} =~ ^\#.* ]]; then
                patterns[$i]=${line}
                values[$((i++))]=${line}
            else
                patterns[$i]=${line%%=*}
                values[$((i++))]=${line##*=}
            fi
        fi
    done < ${thatConfig}

    for ((i=0; i<${#patterns[@]}; i++)); do
        ATTRI_EXISTS=0
        # check if it's a comment
        [[ ${patterns[$i]} =~ ^\#.* ]]
        IS_COMMENT=$?

        for ((k=0; k<${#attributes[@]}; k++)); do
            if [[ ${attributes[$k]} =~ ^${patterns[$i]}=.* ]]; then
                ATTRI_EXISTS=1
                attributes[$k]="${patterns[$i]}=${values[$i]}"
                break
            elif [[ $IS_COMMENT == 0 ]] && [[ "${patterns[$i]}" == "${attributes[$k]}" ]]; then
                ATTRI_EXISTS=1
                break
            fi
        done

        if [[ $ATTRI_EXISTS == 0 ]]; then
            if [[ $IS_COMMENT == 0 ]]; then
                attributes[$((numAttri++))]="${values[$i]}"
            else
                attributes[$((numAttri++))]="${patterns[$i]}=${values[$i]}"
            fi
        fi
    done
    touch "$thisConfig.tmp"
    chmod --reference="$thisConfig" "$thisConfig.tmp"
    for ((i=0; i<$numAttri; i++)); do
        echo "${attributes[$i]}" >> "$thisConfig.tmp"
    done
    mv "$thisConfig"{.tmp,}
}

processCustomConfigFiles() {
    local etcDir="$1"
    local newDir="$2"
    mkdir -p ${etcDir}
    set +e
    for configFile in $(find ${newDir} -maxdepth 1 \( -type f -o -type l \) \( -name "*.properties" -o -name "*.config" -o -name "*.xml" -o -name "*.json" \) -printf "%f\n"); do
        ls $etcDir/$configFile 2>/dev/null
        File_EXISTS=$?
        # currently doesn't apply merge on jvm configs, simply copy and replace
        if [ $File_EXISTS == 0 ] && [ "$configFile" != "jvm.config" ]; then
        # update contents by accepting configFile
            updateConfigByFile $etcDir/$configFile $newDir/$configFile
        else
        # if config is not in the default package then simply copy it
            cp ${newDir}/${configFile} $etcDir/${configFile}
        fi
    done
    set -e
}

declare -a patterns
declare -a values
configDir=
type=
discoveryURI=
nodeEnv=
includeCoordinator=
xmx=

# Process parameters
if [[ $# != 0 ]]; then
    while [[ $# != 0 && -n "$1" ]]; do
        case "$1" in
            -t | --type)
                type="$2"
                shift
                shift
                ;;
            -discoveryURI)
                discoveryURI="$2"
                if [[ $discoveryURI = *" "* ]]; then
                    echo "URI cannot contain spaces"
                    exit 1
                fi
                shift
                shift
                ;;
            -includeCoordinator)
                includeCoordinator="$2"
                if [[ $includeCoordinator != true && $includeCoordinator != false ]]; then
                    echo "includeCoordinator must be boolean"
                    exit 1
                fi
                shift
                shift
                ;;
            -configDir)
                configDir="$2"
                shift
                shift
                ;;
            -jvmXmx)
                xmx="$2"
                if [[ ! $xmx =~ ^[0-9]+[g|G|m|M|k|K]$ ]]; then
                    echo "Invalid xmx"
                    exit 1
                fi
                shift
                shift
                ;;
            *)
                echo "not supported option $1"
                exit 1
                ;;
        esac
    done
fi

# Process configurations
if [ -d "$configDir" ]; then
    processCustomConfigFiles $CONFIG_PATH $configDir
    if [ -d "$configDir/catalog" ]; then
        processCustomConfigFiles $CONFIG_PATH/catalog $configDir/catalog
    fi
    if [ -d "$configDir/filesystem" ]; then
        processCustomConfigFiles $CONFIG_PATH/filesystem $configDir/filesystem
    fi
fi

# check if user specified node.id & node.environment
set +e
tmp=$(grep -s 'node.id' /usr/lib/hetu/etc/node.properties)
NODE_ID=${tmp:8}
NODE_ID_EXISTS=0
[[ -z $NODE_ID ]] && NODE_ID_EXISTS=1

tmp=$(grep -s 'node.environment' /usr/lib/hetu/etc/node.properties)
nodeEnv=${tmp:17}
NODE_ENV_EXISTS=0
[[ -z $nodeEnv ]] && NODE_ENV_EXISTS=1
set -e

if [ -n "$type" ]; then
    case "$type" in
        worker)
            patterns=("^discovery-server.enabled=.*" "^coordinator=.*")
            values=("" "coordinator=false")
            setConfig "$CONFIG_PATH/config.properties"
            echo "Run Hetu engine as worker node"
            ;;
        coordinator)
            patterns=("^coordinator=.*" "^discovery-server.enabled=.*")
            values=("coordinator=true" "discovery-server.enabled=true")
            setConfig "$CONFIG_PATH/config.properties"
            echo "Run Hetu engine as Coordinator node"
            ;;
        *)
            echo "no matching supported server type: \"$type\"; Please specify \"coordinator\" or \"worker\""
            exit 1
    esac
fi

if [ -n "$discoveryURI" ]; then
    echo "Use discovery.uri $discoveryURI"
    patterns=("^discovery.uri=.*")
    values=("discovery.uri=$discoveryURI")
    setConfig "$CONFIG_PATH/config.properties"
fi

if [ -n "$includeCoordinator" ]; then
    echo "Allow scheduling work on the coordinator"
    patterns=("^node-scheduler.include-coordinator=.*")
    values=("node-scheduler.include-coordinator=$includeCoordinator")
    setConfig "$CONFIG_PATH/config.properties"
fi

if [ -n "$xmx" ]; then
   echo "Using jmx setting: -Xmx$xmx"
   patterns=("-Xmx")
   values=("-Xmx$xmx")
   setConfig "$CONFIG_PATH/jvm.config"
fi

if [ $NODE_ID_EXISTS != 0 ]; then
    if [ -n "$nodeEnv" ]; then
        echo "Set node.environment as $nodeEnv"
        NODE_ID="$nodeEnv-${HOSTNAME}"
    else
        nodeEnv="default"
        echo "using default node.environment=test"
        NODE_ID="default-${HOSTNAME}"
    fi
    patterns=("^node.environment=.*" "^node.id=.*")
    values=("node.environment=$nodeEnv" "node.id=$NODE_ID")
    setConfig "$CONFIG_PATH/node.properties"
else
    if [ -n "$nodeEnv" ]; then
        echo "Set node.environment as $nodeEnv"
    else
        nodeEnv="default"
        echo "using default node.environment=test"
    fi
    patterns=("^node.environment=.*")
    values=("node.environment=$nodeEnv")
    setConfig "$CONFIG_PATH/node.properties"
fi

NODE_ID="-Dnode.id=$NODE_ID"
exec /usr/lib/hetu/bin/launcher run ${NODE_ID} "$@"
