#!/bin/bash


GNLAN_CLIENT_NAME=gnLan
GNLAN_INTERFACE=gnLan
CONF_FILE=/etc/stun_client.conf
RCDIR=/etc/rc.d
if [ ! -x "$RCDIR" ]; then
 RCDIR=/etc
fi

export PATH=$PATH:/sbin:/usr/bin
export TempFileList=""
export WorkingPath=`pwd`

GROUP_NAME=""
USER_NAME=""

function ClearTempFiles
{
	#echo "Now delete tempfiles: $TempFileList"
	rm -fr "$TempFileList"
	exit 0
}

function AddTempFile
{
	if [ "$TempFileList" = "" ]; then
		TempFileList=$1
	else
		TempFileList=$TempFileList" $1"
	fi
}

function ChangeWorkingDir
{
	local ProgName=`readlink $1`
	
	#Started command is not a soft link
	[ "$ProgName" = "" ] && ProgName=$1
	local CurrDir=`dirname $ProgName`
	cd $CurrDir
}

function InstallModule
{
	local TunDriverLoaded=`lsmod | grep tun | wc -l`
	[ $TunDriverLoaded -eq 0 ] && modprobe tun

	#Create device file if it does not exist
	[ ! -d /dev/net ] && mkdir /dev/net
	[ ! -e /dev/net/tun ] && mknod /dev/net/tun c 10 200
}

function RunGNLanClient
{
	#Start gnLan client
	local GNLanClientAlreadyRun=`pgrep "$GNLAN_CLIENT_NAME\$" | wc -l`
	[ $GNLanClientAlreadyRun  -ne 0 ] && return 


	local TmpGNLanOutputFile=`mktemp /tmp/tmp.XXXXXXXXXX`
	AddTempFile $TmpGNLanOutputFile

	./$GNLAN_CLIENT_NAME > $WorkingDir/GNLan.log &

	#Then detect whether or not Teamlink interface is up
	local GNLanInterfaceIsUP=0
	local Count=0
	echo -n "Teamlink client \"$GNLAN_CLIENT_NAME\" is logining"
	while [ $GNLanInterfaceIsUP -eq 0 ]; do
		GNLanInterfaceIsUP=`ifconfig $GNLAN_INTERFACE 2> /dev/null | grep -E "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sed -r -e "s/[^0-9]*([0-9.]+) .*/\1/g" | wc -l`
		GNLanClientAlreadyRun=`pgrep "$GNLAN_CLIENT_NAME\$" | wc -l`

		Count=`expr $Count + 1`
		echo -n "."
		sleep 5
		if [ $Count -gt 30 ] || [ $GNLanClientAlreadyRun  -eq 0 ] ; then
			echo -e "\nBring Teamlink interface \"$GNLAN_INTERFACE\" interface up failed!"
			echo "Teamlink client \"$GNLAN_CLIENT_NAME\" may have problem login:"
			killall -9 $GNLAN_CLIENT_NAME 2> /dev/null
			cat $TmpGNLanOutputFile 2> /dev/null
			rm -f $TmpGNLanOutputFile
			return
		fi
	done

	echo
	echo "Successfully started Teamlink client \"$GNLAN_CLIENT_NAME\":"
	cat $TmpGNLanOutputFile 2> /dev/null
	rm -f $TmpGNLanOutputFile
}

function SetMTU
{
	local MTUHasBeenSet=`ifconfig $GNLAN_INTERFACE 2> /dev/null | grep "MTU:1300" | wc -l`
	[ $MTUHasBeenSet -eq 0 ] && ifconfig $GNLAN_INTERFACE mtu 1300
}

function StopGNLan
{
	echo -n "Now stop Teamlink client \"$GNLAN_CLIENT_NAME\"..."
	#First kill gently
	local GNLanClientAlreadyRun=`pgrep "$GNLAN_CLIENT_NAME\$" | wc -l`
	if [ $GNLanClientAlreadyRun  -eq 0 ]; then
		echo -e "\nTeamlink client \"$GNLAN_CLIENT_NAME\" is not running."
		return
	fi

	killall -3 $GNLAN_CLIENT_NAME
	sleep 1

	#Then kill by force
	GNLanClientAlreadyRun=`pgrep "$GNLAN_CLIENT_NAME\$" | wc -l`
	if [ $GNLanClientAlreadyRun  -eq 0 ]; then
		echo "Done"
		return
	fi

	killall -9 $GNLAN_CLIENT_NAME
	sleep 1
	echo "Done"
}

function CheckMqtt
{
        local needRun=true
        local localProgName=""
        localProgName=`ps -ef | grep -v "grep" | grep "$ProgMqttName" | awk '{printf $8}'`

        if [ "$localProgName" == "$WorkingDir/$ProgMqttName" ]; then
                needRun=false
                echo "mqtt is running..."
        else
                echo "mqtt is not running..."
                StartMqtt
        fi

}

function getGroupNameAndUsername() {
    GROUP_NAME=""
    USER_NAME=""

    if [ ! -f "$CONF_FILE" ]; then
        echo "错误：配置文件不存在: $CONF_FILE"
        return 1
    fi

    while IFS='=' read -r key value; do
        key=$(echo "$key" | tr -d '[:space:]')
        value=$(echo "$value" | tr -d '[:space:]')
        if [[ "$key" == \#* ]]; then
            continue
        fi

        if [ "$key" == "groupname" ]; then
            GROUP_NAME="$value"
        elif [ "$key" == "username" ]; then
            USER_NAME="$value"
        fi
    done < "$CONF_FILE"

    if [ -z "$GROUP_NAME" ] || [ -z "$USER_NAME" ]; then
        echo "警告：配置文件中未找到有效的groupname或username"
        return 2  # 用不同返回码标识"文件存在但值缺失"
    fi

    return 0  # 解析成功
}

function StartMqtt
{
	if getGroupNameAndUsername; then
		echo "配置解析成功！"
		echo "组名(GROUP_NAME)：$GROUP_NAME"
		echo "用户名(USER_NAME)：$USER_NAME"
	else
		echo "配置解析失败，错误码：$?"
		return
	fi
        local Instance="STL"

        local current_time=$(date "+%Y%m%d%H%M")

        local tmp_buf="g${GROUP_NAME}_${USER_NAME}n${Instance}wa${current_time}y#2023!"
        local md5_value=$(echo -n "$tmp_buf" | md5sum | awk '{print $1}')

        echo "$tmp_buf $md5_value"

        $WorkingDir/$ProgMqttName $Instance $GROUP_NAME $USER_NAME $md5_value > $WorkingDir/GNMqtt.log 2>&1 &
}

function StopYunMqtt
{
        echo "Stop gnLan mqtt... $WorkingDir/$ProgMqttName"
        killall -9 "$WorkingDir/$ProgMqttName" > /dev/null 2>&1
        sleep 1s
        CheckStatusItem $ProgMqttName
        echo "0" > $WorkingDir/"YunDns.pid"
}

function CheckStatusItem
{
        local localProgName=""
        localProgName=`ps -ef | grep -v "grep" | grep "$1" | awk '{printf $8}'`
        if [ "$localProgName" == "$WorkingDir/$1" ]; then
                echo "$1 is running..."
        else
                echo "$1 is not running..."
        fi

}

function StartGNLan
{
	sed -i -e "s/UserKey1=.*/UserKey1=/" -e "s/UserKey2=.*/UserKey2=/" /etc/stun_client.conf 
	CheckMqtt
	local GNLanClientAlreadyRun=`pgrep "$GNLAN_CLIENT_NAME\$" | wc -l`
	if [ $GNLanClientAlreadyRun  -ne 0 ]; then
                local GNLanIPAddr=`ifconfig $GNLAN_INTERFACE 2> /dev/null | grep -E "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sed -r -e "s/[^0-9]*([0-9.]+) .*/\1/g"`
                if [ "$GNLanIPAddr" != "" ]; then
			echo "Teamlink client \"$GNLAN_CLIENT_NAME\" is already started. Its status:"
			echo "***********************************************************************"
			GNLanStatus
			echo "***********************************************************************"
			return
		fi
	fi

	echo -e "\nNow starting Teamlink client..."
	#First stop buggy running instance
	StopGNLan > /dev/null
	InstallModule
	RunGNLanClient
	SetMTU
}



function GNLanStatus
{
	local ProgName=$1
	local GNLanClientPID=`pgrep "$GNLAN_CLIENT_NAME\$"`

	if [ "$GNLanClientPID" = "" ]; then
		echo "Teamlink client \"$GNLAN_CLIENT_NAME\" does not run."
		echo "Please start it by issuing \"$ProgName start\"."
		return
	fi

	echo "Teamlink client program \"$GNLAN_CLIENT_NAME\" is running, PID: $GNLanClientPID"
	local GNLanIPAddr=`ifconfig $GNLAN_INTERFACE 2> /dev/null | grep -E "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sed -r -e "s/[^0-9]*([0-9.]+) .*/\1/g"`
	if [ "$GNLanIPAddr" = "" ]; then
		echo "Teamlink interface \"$GNLAN_INTERFACE\" is not up, client program may fail to login."
		echo "Please try to restart by issuing \"$ProgName restart\"."
		return
	fi

	echo "Its IP address: $GNLanIPAddr"
	
	CheckStatusItem $ProgMqttName
}

function GNLanInstallSymbolLink
{
	if [ `whoami` != "root" ]; then
		echo "Please install as root user!"
		return
	fi

	local FullProgPath=$1
	local CurrDir=`dirname $FullProgPath`
	local ProgName=`basename $FullProgPath`

	if [ $CurrDir = "." ]; then
		CurrDir=$WorkingPath
		FullProgPath=$WorkingPath/$ProgName
	fi

	#Create symbol link in rcx.d folder
	local CurrRunLevel=`who -r | awk '{print $2}'`
	local AutoLinkName="$RCDIR/rc$CurrRunLevel.d/S99GNLan"

	echo -e -n "\nNow create symbol link: \"$AutoLinkName\"..."

	if [ -e `dirname $AutoLinkName` ]; then
		echo -e "\nSeems your system start script is not located in $RCDIR/, ignore this step."
	fi

	if [ -e $AutoLinkName ]; then
		local TargetFullProgPath=`readlink $AutoLinkName`
		if [ "$TargetFullProgPath" != "$FullProgPath" ]; then
			echo -e "\nSymbol link \"$AutoLinkName\" exists, but it is linked to other file:"
			echo "\"$TargetFullProgPath\""
			echo -n "Do you want to delete old symbol link to proceed the installation?[y|n]:"
			read
			if [ "$REPLY" = "" ] || [ $REPLY = "y" ] || [ $REPLY = 'Y' ]; then
				rm -f $AutoLinkName
			else
				echo "Please manually process the conflict, and then run \"$FullProgPath install\" again!"
				return
			fi
		else
			echo -e "\nSymbol link \"$AutoLinkName\" already exists, we will use the existing one."
			echo "Done"
			return
		fi
	fi

	ln -s $FullProgPath $AutoLinkName
	echo -e "\nSymbol link \"$AutoLinkName\" created!"
	ls -l $AutoLinkName
	echo "Done!"
}


function GNLanInstallCrontab
{
	local FullProgPath=$1
	local CurrDir=`dirname $FullProgPath`
	local ProgName=`basename $FullProgPath`

	if [ $CurrDir = "." ]; then
		CurrDir=$WorkingPath
		FullProgPath=$WorkingPath/$ProgName
	fi

	#Create crontab entry
	echo -e -n "\nNow create crontab entry..."

        local TmpExistingCrontabFile=`mktemp /tmp/tmp.XXXXXXXXXX`
        AddTempFile $TmpExistingCrontabFile	
	crontab -l >$TmpExistingCrontabFile
	
	local CrontabEntry=`crontab  -l | grep "$ProgName" | awk '{print $6}'`
	if [ "$CrontabEntry" ]; then
		if [ "$CrontabEntry" != "$FullProgPath" ]; then
			echo -e "\nThere is already a crontab entry for \"$CrontabEntry\"."
			echo -n "Do you want to delete this one?[y|n]:"
			read
			if [ "$REPLY" = "" ] || [ $REPLY = "y" ] || [ $REPLY = 'Y' ]; then
				#Delete crontab entry from temporiry file 
				sed -i -e "/$ProgName/d" $TmpExistingCrontabFile
			fi
		else
			echo -e "\nCrontab entry \"$CrontabEntry\" already exists, we will use the existing one."
			echo "Done!"
			rm -fr $TmpExistingCrontabFile
			return
		fi
	fi

	#Now real install the crontab entry
	echo "* * * * * $FullProgPath start &" >> $TmpExistingCrontabFile
	crontab $TmpExistingCrontabFile
	rm -fr $TmpExistingCrontabFile

	echo -e "\nCrontabl entry for \"$FullProgPath\" created:"
	crontab -l | grep "$FullProgPath"
	echo "Done!"
}

function CreateConfigFile
{
	if [ -e $CONF_FILE ]; then
		local GroupName=`grep "groupname" $CONF_FILE | awk -F= '{print $2}'`		
		local UserName=`grep "username" $CONF_FILE | awk -F= '{print $2}'`		
		echo "There is already Teamlink config file \"$CONF_FILE\" for $GroupName/$UserName."
		echo -n "Do you want to delet it and generate a new one?[y|n]:"
		read
		if [ "$REPLY" = "" ] || [ $REPLY = "y" ] || [ $REPLY = 'Y' ]; then
			rm -f $CONF_FILE
		else
			return
		fi
	fi

	./$GNLAN_CLIENT_NAME -c
	echo -e '\nLocalPortOffset='$((RANDOM%1000-500)) >> $CONF_FILE
}

function CheckTeamLinkClientProgFile
{
	local FullProgPath=`readlink $1`
	[ "$FullProgPath" = "" ] && FullProgPath=$1
	local CurrDir=`dirname $FullProgPath`
	local ProgName=`basename $FullProgPath`

	if [ $CurrDir = "." ]; then
		CurrDir=$WorkingPath
		FullProgPath=$WorkingPath/$ProgName
	fi

	if [ -f $CurrDir/$GNLAN_CLIENT_NAME ]; then
		[ ! -x $CurrDir/$GNLAN_CLIENT_NAME ] && chmod 755 $FullProgPath
		return
	fi

	echo "There is no teamlink client program: \"$CurrDir/$GNLAN_CLIENT_NAME\"."
	echo "Make sure this program is located in the same directory."
	echo "with \"$FullProgPath\"."
	exit 0
}

function GNLanUnInstallSymbolLink
{
	if [ `whoami` != "root" ]; then
		echo "Please uninstall as root user!"
		return
	fi

	echo -n "Now deleting symbol link..."
	local CurrRunLevel=`who -r | awk '{print $2}'`
	local AutoLinkName="$RCDIR/rc$CurrRunLevel.d/S99GNLan"
	rm -f $AutoLinkName
	echo "Done!"
}

function GNLanUnInstallCrontab
{
	local FullProgPath=$1
	local CurrDir=`dirname $FullProgPath`
	local ProgName=`basename $FullProgPath`

	if [ $CurrDir = "." ]; then
		CurrDir=$WorkingPath
		FullProgPath=$WorkingPath/$ProgName
	fi

	#Create crontab entry
	echo -n "Now deleting crontab entry..."

        local TmpExistingCrontabFile=`mktemp /tmp/tmp.XXXXXXXXXX`
        AddTempFile $TmpExistingCrontabFile	
	crontab -l >$TmpExistingCrontabFile
	
	local CrontabEntry=`crontab  -l | grep "$FullProgPath" | awk '{print $6}'`
	if [ "$CrontabEntry" ]; then
		#Delete crontab entry from temporiry file 
		sed -i -e "/$ProgName/d" $TmpExistingCrontabFile
	fi

	crontab $TmpExistingCrontabFile
	rm -fr $TmpExistingCrontabFile
	echo "Done!"
}


function UninstallOldGNLan
{
	#Kill possible old running programs
	killall gnlan 2> /dev/null
	killall check_stunClient.sh 2> /dev/null

	local CrontabEntry=`crontab  -l | grep "check_stunClient.sh" | awk '{print $6}' | head -1`
	local InstallDir=""

	if [ "$CrontabEntry" ]; then
		echo "Install program found old Teamlink installation, try to uninstall it."
		echo -n "Now deleting crontab entry of old Teamlink installation..."
		InstallDir=`dirname $CrontabEntry`

	        local TmpExistingCrontabFile=`mktemp /tmp/tmp.XXXXXXXXXX`
	        AddTempFile $TmpExistingCrontabFile	
		crontab -l >$TmpExistingCrontabFile
	
		#Delete crontab entry from temporiry file 
		sed -i -e "/check_stunClient.sh/d" $TmpExistingCrontabFile
		crontab $TmpExistingCrontabFile
		rm -fr $TmpExistingCrontabFile
		echo "Done!"
	fi

	if [ -e $RCDIR/rc3.d/S99gnland ]; then
		echo -n "Now deleting rc.d startup script of old Teamlink installation..."
		rm -fr $RCDIR/rc3.d/S99gnland
		echo "Done!"
	fi

	if [ "$InstallDir" ] && [ -d $InstallDir ]; then
		echo -n "Old Teamlink client is installed at \"$InstallDir\", delete the directory?[y|n]:"
		read

		if [ "$REPLY" != "" ] && [ $REPLY = "y" -o  $REPLY = 'Y' ]; then
			rm -fr $InstallDir
		fi

	fi 
}

function ChangeConf
{
	./$GNLAN_CLIENT_NAME -c
}

function main
{
        if [ $(getconf WORD_BIT) = '32' ] && [ $(getconf LONG_BIT) = '64' ] ; then
                GNLAN_CLIENT_NAME=gnLan_64
        fi
        if [[ $(arch) =~ "64" ]] ; then
                GNLAN_CLIENT_NAME=gnLan_64
        fi


	script_abs=$(readlink -f "$0")
	script_dir=$(dirname $script_abs)
	WorkingDir=$script_dir

	ProgMqttName="GNMQTTClient"

	CheckTeamLinkClientProgFile $0
	trap "ClearTempFiles" 2 3 
	ChangeWorkingDir $0
	case "$1" in
		start)
			StartGNLan
			;;
		stop)
			StopGNLan
			echo "Done!"
			;;
		status)
			GNLanStatus $0
			;;
		install)
			UninstallOldGNLan
			StopGNLan
			CreateConfigFile
			GNLanInstallSymbolLink $0
			GNLanInstallCrontab $0
			StartGNLan
			;;
		uninstall)
			GNLanUnInstallSymbolLink
			GNLanUnInstallCrontab $0
			StopGNLan
			StopYunMqtt
			;;
		restart)
			StopGNLan
			StartGNLan
			;;
		config)
			StopGNLan
			ChangeConf
			StartGNLan
			;;
		*)
			echo "Usage: $0 {start|stop|status|restart|install|uninstall|config}"
	esac
}

main $*
