#!/bin/bash
export REMOTE_TEST_PATH=/tmp/remote_test
SCREEN_PATH=$REMOTE_TEST_PATH/screen_tool
export REMOTE_LOG_PATH=$REMOTE_TEST_PATH/log
mkdir -p $REMOTE_LOG_PATH
export REMOTE_LOG_FILE=$REMOTE_TEST_PATH/log.tar.gz
export STATE_DOMAIN=STATE_DOMAIN_TMP
export JOB_ID=JOB_ID_TMP
export STATE_TERMINATOR=STATE_TERMINATOR
export STATE_TERMINATOR_PATH=/tmp/remote_test/state/$STATE_DOMAIN.$JOB_ID.$STATE_TERMINATOR
if ! [[ $PATH =~ $REMOTE_TEST_PATH ]] ; then
   export PATH="$REMOTE_TEST_PATH:$SCREEN_PATH:$PATH"
fi
function source_lib()
{
	local B="lib_trans getlib  $1__$2.tar.gz -extract -source_code -source_lib"
	echo $B
	$B
	B="source source_$1__$2"
	echo $B
	$B
}
function GET_PATH()
{
    local _STATE=${1}
    local flag=${_STATE:0:1}
    if [ "${flag}" == "_" ]; then
        echo "${_STATE}"
        return 0
    fi
    echo "${STATE_DOMAIN}.${JOB_ID}.${_STATE}"
    return 0
}

function SET_STATE()
{
    C_IS_ALIVE StateClient
    if (( $?==1 )) ;then
        echo "Not StateClient"
        return 1
    fi
    local _STATE=${1} 
    local _PATH=`GET_PATH ${_STATE}`
    echo "SET_STATE ${_PATH}=${2}"
    echo "${_PATH}=${2}" > "/tmp/remote_test/state.pipe"
    #fix bug
    sleep 0.2
}

function GET_STATE()
{
    local _STATE=${1} 
    local _PATH=`GET_PATH ${_STATE}`
    _PATH="/tmp/remote_test/state/${_PATH}"
    if [ -f "${_PATH}" ]; then
        value=`cat ${_PATH}`
        #echo $value
        echo "${value}"
    fi
    echo ''
}
function WAIT_STATE()
{
    local _STATE=${1} 
    local _VALUE=${2} 
    local _PATH=`GET_PATH ${_STATE}`
    local value
    _PATH="/tmp/remote_test/state/${_PATH}"
    if [  -n "${_STATE}"  ]; then
        SET_STATE info.wait "${_STATE} ${_VALUE}"
        while true
        do
            if [ -f "${_PATH}" ]; then
                value=`cat ${_PATH}`
                if [ "${value}" == "${_VALUE}" ]; then
                    SET_STATE info.wait_ok "${_STATE} ${_VALUE}"
                    break
                fi
            fi
            if [ -f "${STATE_TERMINATOR_PATH}" ]; then
                value=`cat ${STATE_TERMINATOR_PATH}`
                if [ "${value}" != "" ]; then
                    C_ERROR "${value}" 999
                    break
                fi
            fi
            sleep 0.1
        done
    fi
}
function WAIT_STATE_NOCHECK()
{
    local _STATE=${1} 
    local _VALUE=${2} 
    local _PATH=`GET_PATH ${_STATE}`
    local value
    _PATH="/tmp/remote_test/state/${_PATH}"
    if [  -n "${_STATE}"  ]; then
        SET_STATE info.wait "${_STATE} ${_VALUE}"
        while true
        do
            if [ -f "${_PATH}" ]; then
                value=`cat ${_PATH}`
                if [ "${value}" == "${_VALUE}" ]; then
                    SET_STATE info.wait_ok "${_STATE} ${_VALUE}"
                    break
                fi
            fi
            if [ -f "${STATE_TERMINATOR_PATH}" ]; then
                value=`cat ${STATE_TERMINATOR_PATH}`
                if [ "${value}" != "" ]; then
                    break
                fi
            fi
            sleep 0.1
        done
    fi
}

function KILL_SCREEN()
{  
    local _P1=${1}
    local name=`$SCREEN_PATH/screen  -ls |awk '/'$_P1'/'|awk '{print $1}'`
    for i in ${name[@]};do  
        echo ${i}
        $SCREEN_PATH/screen -S "$i" -X quit
    done
}
function KILL_OLD()
{  
    local _P1=${1}
    local name=`ps -ax | grep -v awk | awk '/'$_P1'/'|awk '{print $1}'`
    for i in ${name[@]};do  
        #echo ${i}
        kill -9  "$i" 
    done
}
function stop_application()
{
    local app=$(basename $1)
    local sigarg=$2
    local pid=`get_process_id $app`
    
    #set +m  
    disown $pid 
    kill $sigarg $pid 
    
}
# function beginswith() 
# { 
#     case $2 in "$1"*) true;; *) false;; esac; 
# }
function check_application_status()
{
    local app=$(basename $1)
    local pid=`get_process_id $app`

    printf "%-20s: " $app

    if [ "$pid" == "" ]; then
        echo "STOPPED"
    else
        echo "RUNNING. PID: $pid"
    fi
}
function get_process_id()
{
    local app=$(basename $1)
    pidof $app
    # local support_option_full=`pgrep --help 2>&1 | grep -o "\-\-full"`

    # if [ ! -z $support_option_full ]; then 
    #     pgrep -l $support_option_full $app | awk '$2=="'$app'" {print $1}'
    #     pidof $app
    #     return
    # fi

    # echo `pgrep $app`
}

function KILL()
{  
    local _P1=${1}
    local count=0
    while true
    do
        pid=`get_process_id $_P1`
        if [ "$pid" == "" ]; then
            break
        fi
        stop_application $(basename $_P1) "-9"
        pid=`get_process_id $_P1`
        if [ "$pid" == "" ]; then
            break
        fi
        ((count+=1))
        if (( count >= 10 ));then
            echo "KILL_failed ${_P1}"
            break
        fi
        sleep 0.5
    done
}
function C_IS_ALIVE()
{  
    local _P1=${1}
    local pid=`get_process_id $_P1`
    if [ "$pid" == "" ]; then
        # 1 = false
        return 1
    else
        # 0 = true
        return 0
    fi
}
function C_REPLACE() {
    local _FILENAME=${1}
    local _TEXT=${2}
    local _CHANGE=${3}
    # ע/ȡעͳ
    if [[ "${_CHANGE}" == "COMMENT" ]]; then
        sed -i "s/^\([ \t]*\)*\(${_TEXT}\)/\1#\2/g" ${_FILENAME}
    elif [[ "${_CHANGE}" == "UNCOMMENT" ]]; then
        sed -i "s/^\([ \t]*\)*#\([ \t]*${_TEXT}\)/\1\2/g" ${_FILENAME}
    else
        sed -i "s~${_TEXT}~${_CHANGE}~g" ${_FILENAME}
    fi
}
function C_REPLACE_BASE()
{
   local _path=${1}
   if [  -n "${_path}"  ]; then
        C_REPLACE  /tmp/remote_test/base_sh      REMOTE_TEST_PATH=/tmp/remote_test   "REMOTE_TEST_PATH=${_path}"
   else
        C_REPLACE  /tmp/remote_test/base_sh      REMOTE_TEST_PATH=/tmp/remote_test   REMOTE_TEST_PATH=\$PWD
   fi
}
function C_SCREEN_ATTACH()
{  
    local _NAME=${1}
    screen -r ${_NAME}
}
function C_SCREEN_DETACH()
{  
    local _NAME=${1}
    screen -d 
}
function C_SCREEN_LIST()
{  
    local _NAME=${1}
    screen -ls | grep -v dead
}
function C_SCREEN_NAME()
{  
    echo $STY
}
function C_SCREEN_CMD()
{  
    local _NAME=${1}
    local _INPUT=${2}
    local cmd=$" echo 123"
    screen -S ${_NAME} -p bash -X $_INPUT
    #screen -S 123 -p bash -X stuff "$cmd"
    #screen -S ${_NAME} -p bash -X stuff $'\r'
}
function C_SCREEN_INPUT()
{  
    local _NAME=${1}
    local _INPUT=${2}
    _INPUT=\$\'$_INPUT\'
    screen -S ${_NAME} -p bash -X stuff $_INPUT
    #screen -S ${_NAME} -p bash -X stuff $'\r'
}
function C_SCREEN_INPUT_AND_ENTER()
{  
    local _NAME=${1}
    local _INPUT=${2}
    _INPUT=\$\'$_INPUT\'
    screen -S ${_NAME} -p bash -X stuff $_INPUT
    screen -S ${_NAME} -p bash -X stuff $'\r'
}
function C_SCREEN_ENTER()
{  
    local _NAME=${1}
    screen -S ${_NAME} -p bash -X stuff $'\r'
}
function C_PAUSE()
{
    local _INFO=${1}
    echo "C_PAUSE ${_INFO}"
    SET_STATE test.info "PAUSE ${_INFO} WAIT_STATE test.state go"
    SET_STATE test.state stop
    WAIT_STATE test.state go
}
function C_SCREEN_NEW()
{  
    local _NAME=${1}
    local fn="${REMOTE_LOG_PATH}/screen_${_NAME}.log"
    screen -L -Logfile ${fn} -S ${_NAME} -dm
}
function C_PACK_LOG()
{  
    tar mzcvf $REMOTE_LOG_FILE  -C $REMOTE_TEST_PATH log
}
function C_CLEAN_UP()
{  
    rm -f $STATE_TERMINATOR_PATH
    echo "clean_up"
}
function C_CLEAN_UP_FOLDER()
{  
    
    rm -rf $REMOTE_TEST_PATH
}

function C_ERROR()
{  
    local _INFO=${1}
    local _CODE=${2}

    local _INFO="${_INFO}_${_CODE}"
   
    SET_STATE $STATE_TERMINATOR "${_INFO}"  
     
    echo "${_INFO}" > $THE_RESULT_FILE
    KILL StateClient
    exit $_CODE
}
function C_ASSERT_FILE()
{  
    local _FILE=${1}
    if [  ! -f "${_FILE}" ]; then
        C_ERROR  "File Not found ${_FILE}"  8002
    fi
}
function C_ASSERT_STATE_IS_EMPTY()
{  
   local _STATE=${1} 
   local _PATH=`GET_PATH ${_STATE}`
   local value
   _PATH="/tmp/remote_test/state/${_PATH}"
   if [ -f "${_PATH}" ]; then
        value=`cat ${_PATH}`
        if [ "${value}" == "" ]; then
            return 0
        fi
        C_ERROR  "${_STATE} = ${value} not empty"  8001
    fi
    #true
    return 0
}
function CHECK()
{
	local MAKE_RET_CODE=$?
    local _INFO=${1} 
	echo "RET CODE is "$MAKE_RET_CODE
	echo $MAKE_RET_CODE > $THE_RESULT_FILE 
	#exit $MAKE_RET_CODE
	if [ $MAKE_RET_CODE -ne 0 ]; then
        C_ERROR "CHECK_${_INFO}" $MAKE_RET_CODE
	fi
}
function CHECK_EXIT_RET()
{
	local MAKE_RET_CODE=${1} 
    local _INFO=${2} 
    local value
	echo "RET CODE is "$MAKE_RET_CODE
	echo $MAKE_RET_CODE > $THE_RESULT_FILE 
    if [ $MAKE_RET_CODE -ne 0 ]; then
            C_ERROR "CHECK_EXIT${_INFO}" $MAKE_RET_CODE
    fi
    if [ -f "${STATE_TERMINATOR_PATH}" ]; then
        value=`cat ${STATE_TERMINATOR_PATH}`
        if [ "${value}" != "" ]; then
            #C_ERROR "${value}" 999
            echo "${value}" > $THE_RESULT_FILE
        fi
    fi
    #echo "EXIT_SCRIPT---------------------"
	exit $MAKE_RET_CODE
}
function CHECK_EXIT()
{
	local MAKE_RET_CODE=$?
    local _INFO=${1} 
    local value
	echo "RET CODE is "$MAKE_RET_CODE
	echo $MAKE_RET_CODE > $THE_RESULT_FILE 
    if [ $MAKE_RET_CODE -ne 0 ]; then
            C_ERROR "CHECK_EXIT${_INFO}" $MAKE_RET_CODE
    fi
    if [ -f "${STATE_TERMINATOR_PATH}" ]; then
        value=`cat ${STATE_TERMINATOR_PATH}`
        if [ "${value}" != "" ]; then
            #C_ERROR "${value}" 999
            echo "${value}" > $THE_RESULT_FILE
        fi
    fi
    #echo "EXIT_SCRIPT---------------------"
	exit $MAKE_RET_CODE
}
function WAIT_TRIGGER()
{
   local _S=${1}
   local _V=${2}
   local _INFO="${_S} ${_V}"
   if [  -n "${_S}"  ]; then
      SET_STATE simpc.info.wait_triger  "${_INFO}"
      WAIT_STATE $_S  $_V
      SET_STATE simpc.info.get_triger  "${_INFO}"
   fi
}
function CHECK_PING()
{
    local _IP=${1}
    timeout -t 10 echo "test"
    if [[ $? != 0 ]];then
        timeout 10 ping -c 2 -w 5 "${_IP}"
    else
        timeout -t 10 ping -c 2 -w 5 "${_IP}"
    fi
    
    if [[ $? != 0 ]];then
        local text=" can not connect ${_IP}"
        C_ERROR "${text}" 1002
        return 1
    fi
    #success
    return 0
} 
function C_ASSERT_RUN ()
{
    local _APP=$1
	local _TIME=$2
    local count=0
    while  ! C_IS_ALIVE $_APP  && (( count < _TIME ));
    do
    ((count+=1))
    SET_STATE ASSERT_RUN  "${_APP}_${_TIME}_${count}"
    sleep 1
    done
    if (( count >= _TIME ));then
        C_ERROR "ASSERT_RUN_${_APP}_${count}" 9001
    fi
}


function C_WAIT_IF_RUNNING ()
{
    local _APP=$1
    local _COUNT=$2
    local count=0
    if [ !  -n "${_COUNT}"  ]; then
        _COUNT=10
    fi
    while  true; 
    do
        sleep 1
        ((count+=1)) 
        C_IS_ALIVE $_APP
        if (( $?==0 )) ;then
            count=0
        fi
        if (( count >= $_COUNT ));then
           break
        fi
    done
    SET_STATE info "${_APP} terminated"
}

function C_TIME()
{
 local t=$(date "+%Y_%m_%d_%H_%M_%S")
 echo "${t}"
}

function C_IS_ERROR()
{  
    local value
    if [ -f "${STATE_TERMINATOR_PATH}" ]; then
        value=`cat ${STATE_TERMINATOR_PATH}`
        if [ "${value}" != "" ]; then
            # 0 = true
            return 0
        fi
    fi
    # 1 = false
    return 1
}
function C_GET_FILESIZE()
{
    local _FN=$1
    ls -l ${_FN} | awk '{print $5}'
}
function C_IS_IN_FILE()
{
    local _FN=$1
    local _TEXT=$2
    grep "${_TEXT}" $_FN >> /dev/null
    if [ $? -ne 0 ]; then
        #not found
        return 1
    fi
    return 0
}
function C_HAS_TEXT()
{
    if [[ $1 =~ $s2 ]]; then
        # true
        return 0
    else
        #false
        return 1
    fi
}
function DOWNLOAD()
{  
    local _URL=$1
    local fn=$(basename "$_URL")
    CMD="curl -o ${fn} -O ${_URL} -g"
    $CMD
    CHECK
    C_GET_FILESIZE "${fn}" 

    if (( $? <1000 )); then
        C_IS_IN_FILE "${fn}" "404 Not Found"
        if [ $? -eq 0 ]; then
            C_ERROR "${fn} 404 Not Found" 449
            return 1
        fi
    fi
    return 0
}
function DOWNLOAD_NOCHECK()
{  
    local _URL=$1
    local fn=$(basename "$_URL")
    CMD="curl -o ${fn} -O ${_URL} -g"
    $CMD
    CHECK
    C_GET_FILESIZE "${fn}" 
    if (( $? <1000 )); then
        C_IS_IN_FILE "${fn}" "404 Not Found"
        if [ $? -eq 0 ]; then
            return 1
        fi
    fi
    return 0
}
function UNZIP()
{  
    local _FN=$1
    _FN=$(basename "$_FN")
    C_HAS_TEXT "${_FN}" ".tar.gz"
    if (( $?==0 )) ;then
        local cmd="tar zxvf ${_FN}"
        $cmd
        CHECK
        return 0
    fi
    C_HAS_TEXT "${_FN}" ".zip"
    if (( $?==0 )) ;then
        local cmd="unzip ${_FN}"
        $cmd
        CHECK
        return 0
    fi
    C_ERROR "Error UNZIP ${_FN}"  472
    return 1
}
function DOWNLOAD_UNZIP()
{  
    DOWNLOAD $1
    UNZIP    $1
}
function ADD_OUTPUT()
{
    local _FN=$1
    _FN=$(realpath  "$_FN")
    if [ -e "${_FN}" ];then
        echo "${_FN}" >> $THE_OUTPUT_LIST
        return 0
    fi
     
    C_ERROR "Not found ${_FN}" 490
    return 1
}
function COPY()
{
    local _FROM=$1
    local _TO=$2
    echo "${_FROM}"
    local cmd="mkdir -p ${_TO}"
    echo "${cmd}"
    $cmd
    cmd="cp -rfp ${_FROM} ${_TO}"
    echo "${cmd}"
    $cmd
    CHECK
}

function TRY_PING()
{
    local _IP=${1}
    timeout -t 10 echo "test"
    if [[ $? != 0 ]];then
        timeout 10 ping -c 2 -w 5 "${_IP}"
    else
        timeout -t 10 ping -c 2 -w 5 "${_IP}"
    fi
    
    if [[ $? != 0 ]];then
        local text=" can not connect ${_IP}"
        return 1
    fi
    #success
    return 0
} 
function C_SETUP_STATE_CLIENT()
{
    local THE_IP=${1}
    echo "${THE_IP}"
    DOWNLOAD_UNZIP http://10.25.15.8:1080/cv2x/release/TOOL/StateSync/TOOL_StateSync_x64/TOOL_StateSync_x64.tar.gz
    if [  -n "${THE_IP}"  ]; then
        TRY_PING  "${THE_IP}"
        if (( $? !=0 )); then
            CHECK "PING_ERROR_${THE_IP}"
        fi
    else
        TRY_PING  192.168.20.199 
        if (( $? ==0 )); then
            THE_IP=192.168.20.199 
            echo $THE_IP
        else
            TRY_PING  10.25.15.53
            if (( $? ==0 )); then
                THE_IP=10.25.15.53
                echo $THE_IP
            else
                CHECK
            fi
        fi
    fi
    chmod +x StateClient
    ./StateClient $THE_IP 2>&1 | tee $REMOTE_LOG_PATH/stateclient.log &
    sleep 0.5
}


function C_WAIT_JOB_DONE()
{
    local _job_id=${1}
    while true
    do
        local _status=`runjob get status  -db_key $_job_id`
        #echo $_status
        if [ "$_status" == "0" ]; then
            echo $_status
            return 0
        fi
        if [ "$_status" == "1" ]; then
            echo $_status
            return 0
        fi
        sleep 1
    done
} 
function SET_JENKINS_INFO()
{
    local _name=${1}
    local _value=${2}
    if [ -e "${THE_INFO_FILE}" ];then
        local _v="$_name = $_value"
        echo  -e $_v >> ${THE_INFO_FILE}
    fi
}

function C_GET_GIT_SHORT_NAME()
{
    local url=${1}
    #https://blog.51cto.com/u_7469027/5394862
    local code_name=${url#*:}
    code_name=${code_name//\//__}
    code_name=${code_name%.*}
    echo $code_name
}


function C_ENDSWITH()
{
    local _TEXT=${1}
    local _X=${2}
	local _X1="${_X}\$"
	#echo $_X1
	#-q -E
	echo "$_TEXT" | grep -q -E "${_X1}"
    if (( $? ==0 )); then
		#echo "yes"
        return 0
    fi
	#echo "no"
    return 1
}
function C_STARTSWITH()
{
    local _TEXT=${1}
    local _X=${2}
	local _X1="^${_X}"
	#echo $_X1
	echo "$_TEXT" | grep  "${_X1}" > /dev/null
    if (( $? ==0 )); then
		#echo "yes"
        return 0
    fi
	#echo "no"
    return 1
}
function C_GIT_CHECK_IS_HASH()
{
    local _COMMIT=${1}
	local _HASH
    _HASH=`git rev-parse "${_COMMIT}"^{commit}`    2> /dev/null
	
    if (( $? !=0 )) ;then
        #echo "error"
		echo ""
        return 1
    fi
    C_STARTSWITH  $_HASH $_COMMIT
    if (( $?==0 )) ;then
        echo $_HASH
        return 0
    fi
    echo ""
    return 1
}

function C_GIT_CLONE()
{
    local _REPO=${1} 
    local _COMMIT=${2} 
	local _HASH
    git init 
    #Fetching upstream changes
    git --version 
    #Cloning repository
    git fetch --tags --force --progress -- "${_REPO}" +refs/heads/*:refs/remotes/origin/* 
    git config remote.origin.url "${_REPO}"
    git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/*

    _HASH=`C_GIT_CHECK_IS_HASH $_COMMIT`
    if (( $?!=0 ))  ;then
        local _TMP_COMMIT=$_COMMIT
        C_STARTSWITH $_TMP_COMMIT origin/
        if (( $?!=0 )) ;then
            _TMP_COMMIT="origin/${_TMP_COMMIT}"
            echo $_TMP_COMMIT
        fi
        _HASH=`git rev-parse "${_TMP_COMMIT}"^{commit}`
    fi
    git config core.sparsecheckout 
    git checkout -f "${_HASH}" # timeout=10

    #git rev-list --no-walk db08749d0be77c1123ff35502cffa24a41d4f226 # timeout=10

    git remote 
    git submodule init 
    git submodule sync 
    git config --get remote.origin.url

    git submodule init # timeout=10

    local _THE_LIST=`git config -f .gitmodules --get-regexp '^submodule\.(.+)\.url'`
    array=(${_THE_LIST})  
    echo $array

    for var in ${array[@]}
    do
        echo $var
        C_ENDSWITH $var .url
        if (( $?!=0 ));then
            continue
        fi
        var=${var#submodule.}
        var=${var%.url}
        git submodule update --init --recursive "${var}"
        
    done 

}


  
# ChangeFileļƺֵ  
function C_CHANGE_FILE() 
{
    local filename=$1  
    local key=$2  
    local newValue=$3  

    # Զѡ񲻻keynewValueͻķָ
    local delimiters='#@|:;%^~'
    local delim
    for d in $(echo $delimiters | fold -w1); do
        if [[ "$key" != *"$d"* && "$newValue" != *"$d"* ]]; then
            delim=$d
            break
        fi
    done
    if [ -z "$delim" ]; then
        echo "޷ҵʵķָ" >&2
        return 1
    fi

    # ʹԶѡķָsed滻
    if sed -i "s${delim}${key} *= *.*\$${delim}${key} = ${newValue}${delim}" "$filename"; then
        if ! grep -q "${key} *= *.*\$" "$filename"; then
            return 1
        fi
    else
       return 1
    fi

    return 0
}
isEmpty() {
    [ -z "$1" ]
}

function safe_remove()
{
    PATH_TO_CHECK=$1
    if [ -L "$PATH_TO_CHECK" ]; then
    # Ƿӣɾ
            rm "$PATH_TO_CHECK"
    else
    
            rm -rf "$PATH_TO_CHECK"
    fi
}

function C_FILESIZE() {
    # Ƿȷ
    if [ "$#" -ne 1 ]; then
        echo "Usage: filesize <filename>" >&2
        return 1
    fi

    # ļǷ
    if [ ! -e "$1" ]; then
        echo "Error: File '$1' does not exist" >&2
        return 2
    fi

    # ǷĿ¼
    if [ -d "$1" ]; then
        echo "Error: '$1' is a directory" >&2
        return 3
    fi

    # òͬȡļС
    local size
    if size=$(stat -Lc '%s' "$1" 2>/dev/null); then    # Linux
        :
    elif size=$(stat -Lf '%z' "$1" 2>/dev/null); then # macOS/BSD
        :
    else
        # ˵ʹls
        size=$(ls -l "$1" | awk '{print $5}' 2>/dev/null)
        [ $? -ne 0 ] && return 4
    fi

    echo "$size"
    return 0
}
