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

[ -n "${PHPCOMMONDEPLOYLIB_VERSION:-}" ] && return 0;
PHPCOMMONDEPLOYLIB_VERSION="0.1";

inherit default exceptor;
$PROGRAM 'awk';
$PROGRAM 'grep';
$PROGRAM 'unzip';
$PROGRAM 'bzip2';
$PROGRAM 'gunzip';
$PROGRAM 'xz';
$PROGRAM 'uncompress';

VERBOSE=0;

[[ -n "${WEBROOT}" ]] && [ ! -d "$WEBROOT" ] && mkdir -p ${WEBROOT};


[ -e "${MANAGE_CORE_PATH}/${COMPUTE_TYPE}"-deploy.lib ] && { include ${COMPUTE_TYPE}-deploy; }


function unpack(){
    APPWEBROOT=$1;
    getPackageName;
    shopt -s dotglob;
    set -f
    rm -Rf ${APPWEBROOT}/*;
    set +f
    shopt -u dotglob;

    ensureFileCanBeUncompressed "${package_path}/${package_name}";
    [[ ! -d "$APPWEBROOT" ]] && { mkdir -p $APPWEBROOT;}
    unset TAR_UNPACK_OPTIONS; unset UNPACK_COMMAND;
    if [[ ${package_url} =~ .zip$ ]] || [[ ${package_name} =~ .zip$ ]]
    then
        $UNZIP -Z -1 "${package_path}/${package_name}" 2>>$ACTIONS_LOG | $GREP -qEw "^/$" && local skip_path="-x /";
        $UNZIP -o "${package_path}/${package_name}" -d "$APPWEBROOT" $skip_path 2>>$ACTIONS_LOG 1>/dev/null;
        rcode=$?;
        [ "$rcode" -eq 1 ] && return 0 || return $rcode
    fi
    if [[ ${package_url} =~ .tar$ ]] || [[ ${package_name} =~ .tar$ ]]
    then
        TAR_UNPACK_OPTIONS="-xpf"
    elif [[ ${package_url} =~ (.tar.gz$|.tgz$) ]] || [[ ${package_name} =~ (.tar.gz$|.tgz$) ]]
    then
        TAR_UNPACK_OPTIONS="-xpzf"
    elif [[ ${package_url} =~ (.tar.bz2$|.tbz$) ]] || [[ ${package_name} =~ (.tar.bz2$|.tbz$) ]]
    then
        TAR_UNPACK_OPTIONS="-xpjf"
    elif [[ ${package_url} =~ (.tar.xz$|.txz$) ]] || [[ ${package_name} =~ (.tar.xz$|.txz$) ]]
    then
        TAR_UNPACK_OPTIONS="-xJf"
    elif [[ ${package_url} =~ (.tar.lzma$|.tlz$) ]] || [[ ${package_name} =~ (.tar.lzma$|.tlz$) ]]
    then
        TAR_UNPACK_OPTIONS="--xz -xf"
    elif [[ ${package_url} =~ (.tar.Z$|.taz$) ]] || [[ ${package_name} =~ (.tar.Z$|.taz$) ]]
    then
        TAR_UNPACK_OPTIONS="-xzf"
    elif [[ ${package_url} =~ .bz2$ ]] || [[ ${package_name} =~ .bz2$ ]]
    then
        UNPACK_COMMAND="$BZIP2 -d"
    elif [[ ${package_url} =~ .gz$ ]] || [[ ${package_name} =~ .gz$ ]]
    then
        UNPACK_COMMAND="$GUNZIP"
    elif [[ ${package_url} =~ (.xz$|.lzma$) ]] || [[ ${package_name} =~ (.xz$|.lzma$) ]]
    then
        UNPACK_COMMAND="$XZ -d"
    elif [[ ${package_url} =~ .Z$ ]] || [[ ${package_name} =~ .Z$ ]]
    then
        UNPACK_COMMAND="$UNCOMPRESS"
    else
        clearCache; deployLog "Archive format of ${package_name} is not supported"; 
        writeJSONResponseErr "result=>4175" "message=>Archive format of ${package_name} is not supported"; die -q;
    fi
    if [ -n "${TAR_UNPACK_OPTIONS}" ] 
        then 
        $TAR --overwrite ${TAR_UNPACK_OPTIONS} "${package_path}/${package_name}" -C "$APPWEBROOT" >> $ACTIONS_LOG 2>&1;
        return $?;
    elif [ -n "${UNPACK_COMMAND}" ] 
        then
        cp ${package_path}/${package_name} ${APPWEBROOT}/${package_name}; ${UNPACK_COMMAND} ${APPWEBROOT}/${package_name} >> $ACTIONS_LOG 2>&1;
        return $?;
    else
        return 1;
    fi 
}

function deployLog(){
        echo -en "$(date) "$@ '\n' >> "$DEPLOY_LOG";
        if [ "$UID" == '0' ]; then
                [ -f "$DEPLOY_LOG" ] && chown -f "$DATA_OWNER" "$DEPLOY_LOG"; 
        fi
}

function shiftContentFromSubdirectory(){
    local appwebroot=$1;
    shopt -s dotglob;
    amount=$(ls $appwebroot | wc -l) ;
    if  [ "$amount" -eq 1 ]
    then
        object=$(ls "$appwebroot");
        if [ -d "${appwebroot}/${object}/${object}" ]
        then
                amount=$(ls "$appwebroot/$object" | wc -l);
                if [ "$amount" -gt 1 ]
                then
                       # in $appwebroot/$object more then one file - exit
                       shopt -u dotglob;
                       return 0;
                fi
                if [ "$amount" -eq 1 ]
                then
                       mv "${appwebroot}/${object}/${object}/"*  "${appwebroot}/${object}/" 2>/dev/null;
                       if [ "$?" -ne 0 ]
                       then
                                shopt -u dotglob;
                                return 0;
                       fi
                fi
                [ -d "${appwebroot}/${object}/${object}" ] && rm -rf "${appwebroot}/${object}/${object}" ;
                shopt -u dotglob;
                return 0;
        fi
        amount=$(ls "$appwebroot/$object" | wc -l) ;
        if [ "$amount" -gt 0 ]
        then
            mv "$appwebroot/$object/"* "$appwebroot/" 2>/dev/null ;
            [ -d "$appwebroot/$object" ] && rm -rf "$appwebroot/$object";
        else
            rmdir "$appwebroot/$object" && [ "x$(basename $appwebroot)" != "xROOT" ] && {
                     [ -d "$appwebroot" ] && { set -f; rm -rf "$appwebroot"; set +f; }
            } ;  writeJSONResponseErr "result=>4072" "message=>Empty package!"; die -q;
        fi
    fi
    shopt -u dotglob;
}


function updateOwnership(){
    shopt -s dotglob;
    APPWEBROOT=$1;
    APPUSER=$($AWK  -F ":" '{ print $1 }' <<< $DATA_OWNER );
    APPGROUP=$($AWK  -F ":" '{ print $2 }' <<< $DATA_OWNER );
    find "$APPWEBROOT" -not -user "$APPUSER" -not -group "$APPGROUP" -print0 | xargs -0 -r chown -f "$DATA_OWNER" 2>>"$JEM_CALLS_LOG" && \
    deployLog "${APPWEBROOT} owner is set to ${DATA_OWNER}" || deployLog "${APPWEBROOT} ownership set failed";
    chmod -Rf a+r,u+w "$APPWEBROOT" 2>>"$JEM_CALLS_LOG" && \
    deployLog "Added read permissions for all, write permissions for ${DATA_OWNER} to ${APPWEBROOT}" || \
    deployLog "Setting read permissions for all, write permissions for ${DATA_OWNER} to ${APPWEBROOT} failed";
    shopt -u dotglob;
}

function prepareContext(){
    local context=$1;
    APPWEBROOT=$WEBROOT/$context/;
}

function deploy(){
    echo "Starting deploying application ..." >> $ACTIONS_LOG 2>&1;
    local package_url=$1;
    local context=$2;
    local ext=$3;
    clearCache;
    prepareContext ${context} ;

    # check exactly FILE - it should not exists, otherwise 'mkdir' returns error
    if [ "x$(basename ${APPWEBROOT})" == "xROOT" ] && [ "x${atomic_deploy}" == "xtrue" ]
    then
        local NEXT_DIR=ROOT_$(date +%Y.%m.%d-%H.%M.%S);
        [ -h ${WEBROOT}/ROOT ] && local CURRENT_DIR=$(readlink ${WEBROOT}/ROOT | $GREP -o "ROOT_[0-9.-]*");
        if [ ! -d ${WEBROOT}/${CURRENT_DIR} ] ; then
                CURRENT_DIR=$(ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | tail -n1);
                [ -n "${CURRENT_DIR}" ] && { ln -sfT ${WEBROOT}/${CURRENT_DIR}/ ${WEBROOT}/ROOT && deployLog "Switching the ROOT context to ${CURRENT_DIR} directory";} || CURRENT_DIR=" ";
        fi
        local PREVIOUS_DIR=$(ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | $GREP -v "$CURRENT_DIR" | head -1);
        if [ -z "${PREVIOUS_DIR}" ] ;then
                local DIR_AMOUNT=$(ls "${WEBROOT}" | $GREP -c "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$");
                [ ${DIR_AMOUNT} -gt 1 ]  && PREVIOUS_DIR=$(ls "${WEBROOT}" | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | tail -n2 | head -1);
        fi
        [ -n "${PREVIOUS_DIR}" ] && rm -rf ${WEBROOT}/${PREVIOUS_DIR} && deployLog "Removing old deprecated application directory ${PREVIOUS_DIR}";
        [[ -d "${WEBROOT}/ROOT/" && ! -h ${WEBROOT}/ROOT ]] && rm -rf ${WEBROOT}/ROOT/ && deployLog "Removing existing ROOT directory";
        unpack ${WEBROOT}/${NEXT_DIR}/ && deployLog "Unpacking application to new ROOT context directory ${NEXT_DIR}" || { rm -rf ${WEBROOT}/${NEXT_DIR}/ 1>/dev/null 2>&1; writeJSONResponseErr "result=>4071" "message=>Cannot unpack package" && deployLog "Not enough disk space. Cannot unpack application to new context directory"; die -q; };
        shiftContentFromSubdirectory ${WEBROOT}/${NEXT_DIR}/;
        updateOwnership ${WEBROOT}/${NEXT_DIR}/;
        ln -sfT ${WEBROOT}/${NEXT_DIR}/ ${WEBROOT}/ROOT && deployLog "Switching the ROOT context to ${NEXT_DIR} directory";
        APPWEBROOT=${WEBROOT}/ROOT;
    else
        undeploy ${context};
        unpack $APPWEBROOT  || { rm -rf $APPWEBROOT 1>/dev/null 2>&1; writeJSONResponseErr "result=>4071" "message=>Cannot unpack package"; die -q; }
        shiftContentFromSubdirectory $APPWEBROOT;
        setContext $context;
        echo "Application deployed successfully!" >> $ACTIONS_LOG 2>&1;
        deployLog "Application successfully deployed to $APPWEBROOT";
    fi
    finishDeploy;
}

function finishDeploy(){
    updateOwnership $APPWEBROOT;
    clearCache;
}

function undeploy(){
    local context=$1;
    if [ "x$context" == "xROOT" ]
    then
        APPWEBROOT=${WEBROOT}/ROOT;
    [ -h $APPWEBROOT ] && { rm -f $APPWEBROOT; cd ${WEBROOT}; ROOT_DIRS=$(ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$"); rm -rf ${ROOT_DIRS} && deployLog "Removing ROOT context and all the related directories: ${ROOT_DIRS}"; }
        if [[ -d "$APPWEBROOT" ]]
        then
                rm -Rf $APPWEBROOT && deployLog "Content of $APPWEBROOT directory deleted";
        else
                mkdir $APPWEBROOT;
                updateOwnership $APPWEBROOT;
        fi
    else
        APPWEBROOT=$WEBROOT/$context
        if [[ -d "$APPWEBROOT" ]]
    then
        rm -Rf $APPWEBROOT && deployLog "Directory $APPWEBROOT removed";
    fi
        delContext $context;
    fi
}

function renameContext(){
    local newContext=$1;
    local oldContext=$2;
    if [ ! -d "$WEBROOT/$newContext" ]
    then
        mkdir -p "$WEBROOT/$newContext";
    else
        shopt -s dotglob
        set -f
        rm -Rf "$WEBROOT/$newContext/"* && deployLog "Content of $newContext directory removed";
        set +f
        shopt -u dotglob
    fi

    if [ ! -h "${WEBROOT}/${oldContext}" ]; then
    if [ -d "${WEBROOT}/${oldContext}" ]
    then
        if [ "$UID" == '0' ]; then
              chown -R ${DATA_OWNER} "${WEBROOT}/${oldContext}";
        fi 
        shopt -s dotglob;
        mv "$WEBROOT/$oldContext/"* "$WEBROOT/$newContext/" 2>/dev/null && [ "$oldContext" != "ROOT" ] && rm -rf $WEBROOT/$oldContext;
        deployLog "Moving application data from $oldContext to $newContext";
        shopt -u dotglob;
    else
        writeJSONResponseErr "result=>4052" "message=>Context does not exist"; die -q;
    fi
    fi

    if [ "x${newContext}" == "xROOT" ]
    then
        set -f
        rm -Rf $WEBROOT/$oldContext/ 2>/dev/null && deployLog "Directory $oldContext deleted";
        set +f
        delContext $oldContext;
        return 0;
    else
    if [ "x${oldContext}" == "xROOT" ]
        then
            if [ -h ${WEBROOT}/ROOT ]
            then
                local CURRENT_DIR=$(readlink ${WEBROOT}/ROOT | $GREP -o "ROOT_[0-9.-]*");
                [ ! -d ${WEBROOT}/${CURRENT_DIR} ] && CURRENT_DIR=$(ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | tail -n1);
                [ ! -n ${CURRENT_DIR} ] && { writeJSONResponseErr "result=>4052" "message=>Context does not exist"; die -q; }
                if [ -d ${WEBROOT}/${CURRENT_DIR} ] ;then
                        if [ "$UID" == '0' ]; then
                            chown -R ${DATA_OWNER} ${WEBROOT}/${CURRENT_DIR};
                        fi 
                        shopt -s dotglob;
                        set +f
                        mv ${WEBROOT}/${CURRENT_DIR}/* ${WEBROOT}/${newContext} 2>/dev/null && deployLog "Moving application data from ${CURRENT_DIR} to ${newContext}";
                        shopt -u dotglob;
                fi
                rm -rf ${WEBROOT}/ROOT; cd ${WEBROOT}; ROOT_DIRS=$(ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$"); rm -rf ${ROOT_DIRS} && deployLog "Removing ROOT context directories ${ROOT_DIRS}";
                [ ! -d ${WEBROOT}/ROOT ] && mkdir ${WEBROOT}/ROOT;
            fi
        setContext $newContext;
        else
        rm -Rf $WEBROOT/${oldContext} 2>/dev/null && deployLog "Directory ${oldContext} deleted";
        isFunction "rename" && rename $newContext $oldContext ;
        fi
    fi
    updateOwnership "$WEBROOT/$newContext"

}
