#!/bin/bash

# Copyright: 2023 Virtuozzo International GmbH

# 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.



inherit default os envinfo hooks;
include output decrypt-passwd;

DESCRIPTION="Enables SSL for application stack";
VERSION="1";
DEFAULT_ACTION="Usage";
VCS_CONFIG_DIR="/var/lib/jelastic/vcs";
DEFAULT_DOMAIN="jelastic";

HOOKS_DIR="/var/lib/jelastic/hooks";

export GIT_SSL_NO_VERIFY=true;
JELASTIC_API="api.jelastic.com"
LOG_DIR="/var/log/maven"
MVN='/opt/maven/bin/mvn'
MAVEN_PLUGIN_VERSION="";
$PROGRAM 'svn';
$PROGRAM 'git';
$PROGRAM 'curl';
$PROGRAM 'java';
$PROGRAM 'zip';
$PROGRAM 'grep';
$PROGRAM 'awk';
APP_ROOT=$WEBROOT;
DEPLOY_PROPROPERTIES="/tmp/dep_prop.tmp";

free_mem=`free -m | $GREP Mem | $AWK '{print $2}'`;

. /etc/profile &>>/var/log/maven/hooks.log

function parseArguments() {
    EXTRA_BUILD_DEPLOY_PARAM=''
    local res=0
    decryptPassword $@
    res=$?
    [ $res -eq 0 ] || die -q
    set -- ${JEM_PARAMS[@]};
while [ "$1" != "" ]; do
  case $1 in

    -n  | --project-name )      shift;
                                PROJECT_NAME=$1;
                                ;;
    -a  | --api-host )          shift;
                                API_HOST=$1;
                                ;;
    -s  | --session )           shift;
                                SESSION=$1;
                                ;;
    -mpv | --maven-plugin-version )  shift;
                                MAVEN_PLUGIN_VERSION=$1;
                                ;;                                
    -h  | --host-headers )      shift;
                                HOST_HEADERS=$1;
                                ;;
    -t  | --vcs-type )          shift;
                                VCS_TYPE=$1;
                                ;;
    -u  | --url )               shift;
                                URL=$1;
                                ;;
    -l  | --login )             shift;
                                LOGIN=$1;
                                ;;
    -p  | --password )          shift;
                                PASSWORD=$1;
                                ;;
    -b  | --branch )            shift;
                                BRANCH=$1;
                                ;;
    -o  | --old-project-name )  shift;
                                OLD_PROJECT_NAME=$1;
                                ;;
    -c  | --context )           shift;
                                CONTEXT=$1;
                                ;;
    -e  | --environment )       shift;
                                ENVIRONMENT=$1;
                                ;;
    -au | --autoupdate )        shift;
                                AUTOUPDATE=$1;
                                ;;
    -su | --skip-upload )       shift;
                                SKIP_UPLOAD=$1;
                                ;;
    --update )                  shift;
                                UPDATE=$1;
                                ;;
    --build )                   shift;
                                BUILD=$1;
                                ;;
    -m  | --updateinverval | -i  | --interval )    shift;
                                UPDATE_INTERVAL=$1;
                                ;;
    --subdirectory )	shift;
                                BUILDDIR=$1;
                                ;;
    -g | --nodegroup )
                                shift;
                                NODE_GROUP=$1
                                ;;
    --repohash )
                                shift;
                                REPO_HASH=$1
                                ;;
    --actionkey )
                                shift;
                                EXTRA_BUILD_DEPLOY_PARAM="-Daction-key=\"$1\""
                                ;;
  esac
  shift
done
}

[ -z "$UPDATE" ] && UPDATE="true";
[ -z "$BUILD" ] && BUILD="true";

function checkProjectsDirectory(){
    [ ! -d  $APP_ROOT ] && mkdir -p $APP_ROOT;
}

function doCreateProject(){
    local err;
    checkProjectsDirectory;
    doAction vcs createproject "$@";
    err=$?; [[ ${err} -gt 0 ]] && exit ${err};
}

function doDeleteProject(){
    local err;
    doAction vcs deleteproject "$@";
    err=$?; [[ ${err} -gt 0 ]] && exit ${err};
}

function doGetProject(){
    local err;
    doAction vcs getproject "$@";
    err=$?; [[ ${err} -gt 0 ]] && exit ${err};
}

function doUpdate(){
    local err;
    local msg=$( doAction vcs update "$@" );
    $GREP -q 'result\":\"0' <<< $msg || { echo $msg 1>&2; die -q; }
#   err=$?; [[ ${err} -gt 0 ]] && exit ${err};
}

function doEditProject(){
    local err;
    doAction vcs editproject "$@";
    err=$?; [[ ${err} -gt 0 ]] && exit ${err};
}

function generateDeployProperties(){
    [ -f "$DEPLOY_PROPROPERTIES" ] && rm "$DEPLOY_PROPROPERTIES";
    echo "environment=${ENVIRONMENT}" >> $DEPLOY_PROPROPERTIES;
    echo "context=${CONTEXT}" >> $DEPLOY_PROPROPERTIES;
    echo "nodegroup=${NODE_GROUP}" >> $DEPLOY_PROPROPERTIES;
}

function readProjectConfig(){
    local project_to_read;
    BUILDDIR='';
    [ -z "$1" ] && project_to_read=${PROJECT_NAME} || project_to_read="$1";
    if [ -e "${VCS_CONFIG_DIR}/${project_to_read}.properties" ] ; then
      source "${VCS_CONFIG_DIR}/${project_to_read}.properties";
      [ -z $VCS_TYPE ] && {
          #echo "You must specify version control system";
          return 1;
      }
      [ ! -z "$ENVIRONMENT" ] && hash idn 2>/dev/null && { ENVIRONMENT=`idn --quiet $ENVIRONMENT`; }
      return 0;
      else
            #echo "Couldn't find project options!";
            return 1;
      fi
}

function doBuild(){ 
    BUILD_IS_OK="false";
    parseArguments "$@"  || return 1;
    readProjectConfig;
    [ "x$UPDATE" == "xtrue" ] && doUpdate update -n $PROJECT_NAME;
    [[ ${BUILDDIR} =~ pom.xml$ && -f "${APP_ROOT}/${PROJECT_NAME}/${BUILDDIR}" ]] && BUILDDIR=${BUILDDIR/pom.xml};
    if [ -e "${APP_ROOT}/${PROJECT_NAME}/${BUILDDIR}/pom.xml" ] ; then
        cd "${APP_ROOT}/${PROJECT_NAME}" &>>"$JEM_CALLS_LOG";
        echo "export APP_ROOT=${APP_ROOT}" >$STACK_PATH/jeltmp 2>>"$JEM_CALLS_LOG";
        echo "export PROJECT_NAME=${PROJECT_NAME}" >>$STACK_PATH/jeltmp 2>>"$JEM_CALLS_LOG";

        applyHook ${PROJECT_NAME} preBuild || { rm -rf $STACK_PATH/jeltmp; writeJSONResponseErr "result=>4129" "message=>Pre-build hook execution failed. See hooks log for details: ${HOOKS_LOG}"; return 1; };
        #echo "Building $m_name ..."
        tmpUpload=$(mktemp --suffix mvn)
        chmod a+w $tmpUpload 2>/dev/null
        [ -f "$tmpUpload" ] && EXTRA_BUILD_DEPLOY_PARAM="${EXTRA_BUILD_DEPLOY_PARAM} -DuploadLogPath=$tmpUpload"        
        PROJECT_MNV_ARGS=$(env | grep -m 1 -i $(echo  MAVEN_RUN_ARGS_$( sed -re 's/(\s|-)/_/g' <<< "$PROJECT_NAME" ))|cut -f 1 -d '=' --complement)
        echo "[RUN-INFO] mvn clean ${PROJECT_MNV_ARGS} ${MAVEN_RUN_ARGS} clean install --file \"${APP_ROOT}/${PROJECT_NAME}/${BUILDDIR}/pom.xml\"" >> "${LOG_DIR}/${PROJECT_NAME}_build.log";
        chown "$DATA_OWNER" -R "${LOG_DIR}" &>>"$JEM_CALLS_LOG"
        runuser jelastic -c "$MVN ${PROJECT_MNV_ARGS} ${MAVEN_RUN_ARGS} clean install --file \"${APP_ROOT}/${PROJECT_NAME}/${BUILDDIR}/pom.xml\" ${EXTRA_BUILD_DEPLOY_PARAM} >> \"${LOG_DIR}/${PROJECT_NAME}_build.log\" 2>&1" && { 
        BUILD_IS_OK="true"; applyHook ${PROJECT_NAME} postBuild || { rm -rf $STACK_PATH/jeltmp; writeJSONResponseErr "result=>4130" "message=>Post-build hook execution failed. See hooks log for details: ${HOOKS_LOG}"; return 1; }; }
        rm -rf $STACK_PATH/jeltmp;
        if [ "x$BUILD_IS_OK" == "xtrue" ] ; then
            if [ "x$SKIP_UPLOAD" == "xtrue" ] ; then
                writeJSONResponseOut "result=>0" "message=>Build success"; 
                return 0;
            fi
            runuser jelastic -c "$MVN ${PROJECT_MNV_ARGS} ${MAVEN_RUN_ARGS} com.jelastic:jelastic-maven-plugin:${MAVEN_PLUGIN_VERSION}:publish $maven_opts -Djelastic-comment=\"${PROJECT_NAME}\" -Djelastic-headers=\"$HOST_HEADERS\" -Djelastic-hoster=\"$API_HOST\"  -Djelastic-upload-only=true -Djelastic-session=\"$SESSION\" --file \"${APP_ROOT}/${PROJECT_NAME}/${BUILDDIR}/pom.xml\" ${EXTRA_BUILD_DEPLOY_PARAM}" >> "${LOG_DIR}/${PROJECT_NAME}_deploy.log" 2>&1;
            [ $? -eq 0 ] && {
                local tmpUploadInfo='';
                [ -f $tmpUpload ] && tmpUploadInfo=$(cat $tmpUpload 2>/dev/null);
                rm -rf $tmpUpload ;
                writeJSONResponseOut "result=>0" "message=>Build success" "uploadinfo=>$tmpUploadInfo"; 
                return 0;
            } || {
                writeJSONResponseErr "result=>4049" "message=>Upload failed, see logs for details" ; return 1 ;
            };
        else
            writeJSONResponseErr "result=>4059" "message=>Build failed, see logs for details" ; return 1 ;
        fi
    else
        echo "[ERROR] File pom.xml is absent" >> "${LOG_DIR}/${PROJECT_NAME}_build.log"
        writeJSONResponseErr "result=>4133" "message=>File pom.xml is absent";
        return 1;
    fi
}

function doDeploy(){
    BUILD_IS_OK="false";
    parseArguments "$@"  || return 1;
    readProjectConfig;
    [ "x$UPDATE" == "xtrue" ] && doUpdate update -n $PROJECT_NAME;
    #echo "Deploying $m_name ..."
    [[ ${BUILDDIR} =~ pom.xml$ && -f "${APP_ROOT}/${PROJECT_NAME}/${BUILDDIR}" ]] && BUILDDIR=${BUILDDIR/pom.xml};
    if [ -e "${APP_ROOT}/${PROJECT_NAME}/${BUILDDIR}/pom.xml" ] ; then
        cd "${APP_ROOT}/${PROJECT_NAME}" &>>"$JEM_CALLS_LOG"
        chown "$DATA_OWNER" -R "${LOG_DIR}" &>>"$JEM_CALLS_LOG"
        PROJECT_MNV_ARGS=$(env | grep -m 1 -i $(echo  MAVEN_RUN_ARGS_$( sed -re 's/(\s|-)/_/g' <<< "$PROJECT_NAME" ))| cut -f 1 -d '=' --complement )
        if [ "x$BUILD" == "xtrue" ]; then
            applyHook ${PROJECT_NAME} preBuild || { writeJSONResponseErr "result=>4129" "message=>Pre-build hook execution failed. See hooks log for details: ${HOOKS_LOG}"; return 1; };
            echo "[RUN-INFO] mvn clean ${PROJECT_MNV_ARGS} ${MAVEN_RUN_ARGS} clean install --file \"${APP_ROOT}/${PROJECT_NAME}/${BUILDDIR}/pom.xml\"" >> "${LOG_DIR}/${PROJECT_NAME}_build.log";
            chown "$DATA_OWNER" -R "${LOG_DIR}" &>>"$JEM_CALLS_LOG"
            runuser jelastic -c "$MVN ${PROJECT_MNV_ARGS} ${MAVEN_RUN_ARGS} clean install --file \"${APP_ROOT}/${PROJECT_NAME}/${BUILDDIR}/pom.xml\" ${EXTRA_BUILD_DEPLOY_PARAM}" >> "${LOG_DIR}/${PROJECT_NAME}_build.log" 2>&1 && { BUILD_IS_OK="true"; applyHook ${PROJECT_NAME} postBuild || { writeJSONResponseErr     "result=>4130" "message=>Post-build hook execution failed. See hooks log for details: ${HOOKS_LOG}"; return 1; }; }
        else
            BUILD_IS_OK="true";
        fi
        readProjectConfig $PROJECT_NAME;
        generateDeployProperties;
        if [ "x$BUILD_IS_OK" == "xtrue" ] ; then
            local jelastic_hooks=''
            [ -f "$HOOKS_DIR/preDeploy_${PROJECT_NAME}.sh" ] && jelastic_hooks="-Djelastic-predeploy-hook=$HOOKS_DIR/preDeploy_${PROJECT_NAME}.sh"
            [ -f "$HOOKS_DIR/postDeploy_${PROJECT_NAME}.sh" ] && jelastic_hooks="$jelastic_hooks -Djelastic-postdeploy-hook=$HOOKS_DIR/postDeploy_${PROJECT_NAME}.sh"
            runuser jelastic -c "$MVN ${PROJECT_MNV_ARGS} ${MAVEN_RUN_ARGS} com.jelastic:jelastic-maven-plugin:${MAVEN_PLUGIN_VERSION}:deploy $maven_opts -Djelastic-comment=\"${PROJECT_NAME}\" -Djelastic-headers=\"$HOST_HEADERS\" -Djelastic-hoster=\"$API_HOST\" -Djelastic-properties=\"$DEPLOY_PROPROPERTIES\" -Dcontext=\"$CONTEXT\" -Denvironment=\"$ENVIRONMENT\" -Djelastic-session=\"$SESSION\" -Dpackaging.type=\"war\" $jelastic_hooks --file \"${APP_ROOT}/${PROJECT_NAME}/${BUILDDIR}/pom.xml\" ${EXTRA_BUILD_DEPLOY_PARAM}" >> "${LOG_DIR}/${PROJECT_NAME}_deploy.log" 2>&1;
            [ $? -eq 0 ] && { 
                [ -f "$DEPLOY_PROPROPERTIES" ] && rm "$DEPLOY_PROPROPERTIES" ; 
            } || { 
                writeJSONResponseErr "result=>4060" "message=>Deploy failed, see logs for details" ; return 1 ;
            };
        fi
    else
                echo "[ERROR] File pom.xml is absent" >> "${LOG_DIR}/${PROJECT_NAME}_build.log"
        writeJSONResponseErr "result=>4059" "message=>Build failed, see logs for details" ; return 1 ;
    fi
}

function describeBuild() {
    echo "Build project";
}

function describeBuildParameters() {
    echo "-n|--project-name <name> -s <> -mpv <> -a app.dev.jelastic.com -h <>";
}

function describeBuildOptions() {
    echo "-n|--project-name: project name -su|--skip-upload: <true/false> ";
}

function describeCreateProject() {
    echo "Create new project";
}

function describeCreateProjectParameters() {
    echo "-n|--project-name <name> -t|--vcs-type <git|svn> -u|--url <url> -l|--login <login> [-p|--password <password>] \n\t-b|--branch <branch name> -c|--context <context> -e|--environment <environment name> -au|--autoupdate <true|false>\n\t-i|--inverval <interval>|--update <true|false>|--build <true|false>-g|--nodegroup:nodegroup <group name>";
}

function describeCreateProjectOptions() {
    echo "-au|--autoupdate: allow auto update feature (true|false)";
    echo "-b|--branch: branch ";
    echo "-c|--context: context for deploy";
    echo "-e|--environment: environment name ";
    echo "-l|--login: login ( __GUEST__ )";
    echo "-i|--inverval: interval or autoupdates";
    echo "-n|--project-name: project name";
    echo "-p|--password: password";
    echo "-su|--skip-upload: <true/false>";
    echo "-t|--vcs-type: project type";
    echo "-u|--url:project url";
    echo "-g|--nodegroup:nodegroup name";
    echo "--update: sets if project should be updated before build or not (\"true\" by default)";
    echo "--build: sets if project should be built before deploy or not (\"true\" by default)";
}


function describeDeleteProject() {
    echo "Delete project";
}

function describeDeleteProjectParameters() {
    echo "-n|--project-name <name>";
}

function describeDeleteProjectOptions() {
    echo "-n|--project-name: project name";
}

function describeDeploy() {
    echo "Deploy project";
}

function describeDeployParameters() {
    echo "-s|--session <session> -mpv|--maven-plugin-version <version> -a|--api-host <api host> -n|--project-name <name> -h|--host-headers <headers>|--update <true|false>|--build <true|false>";
}

function describeDeployOptions() {
    echo "-s|--session: session";
    echo "-mpv|--maven-plugin-version: maven plugin version";
    echo "-a|--api-host: API host name";
    echo "-n|--project-name: project name";
    echo "-h--host-headers: headers";
    echo "--update: sets if project should be updated before build or not (\"true\" by default)";
    echo "--build: sets if project should be built before deploy or not (\"true\" by default)";
}

function describeEditProject() {
    echo "Edit project";
}

function describeEditProjectParameters() {
    echo "-n|--project-name <name> -o|--old-project-name <old project name> -t|--vcs-type <git|svn> -u|--url <url>\n\t-l|--login <login> [-p|--password <password>] -b|--branch <branch name> -c|--context <context>\n\t-e|--environment <environment name> -au|--autoupdate <true|false> -i|--inverval <interval>|--update <true|false>|--build <true|false> -g|--nodegroup <group name>";
}

function describeEditProjectOptions() {
    echo "-au|--autoupdate: allow auto update feature (true|false)";
    echo "-b|--branch: branch ";
    echo "-c|--context: context for deploy";
    echo "-e|--environment: environment name ";
    echo "-l|--login: login ( __GUEST__ )";
    echo "-i|--inverval: interval or autoupdates";
    echo "-n|--project-name: project name";
    echo "-o|--old-project-name: old project name";
    echo "-p|--password: password";
    echo "-t|--vcs-type: project type";
    echo "-u|--url:project url";
    echo "-g|--nodegroup:nodegroup name";
    echo "--update: sets if project should be updated before build or not (\"true\" by default)";
    echo "--build: sets if project should be built before deploy or not (\"true\" by default)";
}

function describeGetProject() {
    echo "Get project settings";
}

function describeGetProjectParameters() {
    echo "-n|--project-name <name>";
}

function describeGetProjectOptions() {
    echo "-n|--project-name: project name";
}

function describeUpdate() {
    echo "Update project";
}

function describeUpdateParameters() {
    echo "-n|--project-name <name>";
}

function describeUpdateOptions() {
    echo "-n|--project-name: project name";
}
