#!/bin/bash

led='/usr/sbin/iTalk/led'

blink() 
{
    while true; do
        $led -l2 -o1  # Turn on the LED
        sleep 0.5
        $led -l2 -o0  # Turn off the LED
        sleep 0.5
    done
}

UpdateService()
{
    for service_file in /lib/systemd/system/ua-*.service; do
        if [ ! -f "$1/Environment/Service/$(basename "$service_file")" ]; then
            systemctl disable "$(basename "$service_file")"
            rm -f "$service_file"
        fi
    done
    
}

DeleteServiceEnvironment()
{
   
    rm -rf /lib/systemd/system/ua-*;
}
KeepProjectFile()
{
	mkdir /tmp/Project/;
	cp -rf /app/Web/public/File /tmp/Project/;
	rm /tmp/Project/File/Version.txt;
	cp -rf /app/Web/cgi-bin /tmp/Project/;
	cp -rf /app/Certificates /tmp/Project/;
    cp -rf /app/DDNS/inadyn.conf /tmp/Project;
    cp -rf /app/MQTT/Broker/mosquitto.conf /tmp/Project/;
    cp -rf /app/runtime/project /tmp/Project/;
    cp -rf /app/Wireless/wvdial.conf /tmp/Project/;
    cp -rf /app/firewall/blocklist/rule_config.json /tmp/Project/;
    cp -rf /app/SNMP/File/snmpd.conf /tmp/Project/;
    cp -rf /app/SNMP/File/Transform.json /tmp/Project/;

	rm -rf /app/Web/public/File/TCP_Module/TcpIcpdasModule.json;
	rm -rf /app/Web/public/File/RTU_Module/RtuIcpdasModule.json;
}

RestoreProjectFiles()
{
	#2024/01/11
	cp -rf /tmp/Project/File /app/Web/public/;
	cp -rf /tmp/Project/cgi-bin /app/Web/;
	cp -rf /tmp/Project/Certificates /app/;
    cp -rf /tmp/Project/inadyn.conf /app/DDNS;
    cp -rf /tmp/Project/mosquitto.conf /app/MQTT/Broker/;
    cp -rf /tmp/Project/project /app/runtime/;
    cp -rf /tmp/Project/wvdial.conf /app/Wireless/;
    cp -rf /tmp/Project/rule_config.json /app/firewall/blocklist/;
    cp -rf /tmp/Project/snmpd.conf /app/SNMP/File/;
    cp -rf /tmp/Project/Transform.json /app/SNMP/File/;

	rm -rf /tmp/Project/;
	Sync;
}

WebUpdateCheckTarFileName()
{
    Total=`ls -l /mnt/SD/update/*.tar  | grep "^-" | wc -l`;
    if [ "$Total" != "1" ]; then
        expr -1;
        return;
    fi
    
    Path="/mnt/SD/update/";
    TarName=`ls "$Path"ua-arm64*.tar`;
    if [ "$TarName" = "" ]; then
        expr 0;
        return;
    fi

    expr 1;
}

RenameAPPFolder()
{
	rm -rf /app_old;
	mv /app /app_old;
	Sync;
}

WriteStringToWebLog()
{
	echo "$1" > /tmp/WebUpdate.log;
}

WebUpdateDecompressedFile()
{
    
	tar --warning=no-timestamp -xf /mnt/SD/update/ua-arm64*.tar -C /.;
	if [ $? -ne 0 ]; then
		WriteStringToWebLog "Step2: Decompressed Firmware Fail.";
		rm -rf /command*.sh;
        rm -rf /command*.sh;
        rm -rf /function.sh;
        rm -rf /Environment;
        rm -rf /app.tar.gz ;
        rm -rf /rotarySwitch.sh;      
		mv /app_old /app;
		rm -rf /mnt/SD/update;
		mv /mnt/SD/factory_old /factory;
		Beep 4 0.25 0.1;
		exit 0;
	fi

	tar --warning=no-timestamp -zxf /app.tar.gz -C /.;
	if [ $? -ne 0 ]; then
		WriteStringToWebLog "Step2: Decompressed Firmware Fail.";
		rm -rf /app;
		rm -rf /command*.sh /function.sh /Environment /app.tar.gz /rotarySwitch.sh;
		mv /app_old /app;
		mv /mnt/SD/factory_old /factory;
		rm -rf /mnt/SD/update;
		Sync;
		systemctl start ua-runtime.service ua-broker.service ua-backstageService.service ua-snmpd.service ua-iftttConditionTrigger.service;
		Beep 4 0.25 0.1;
		exit 0;
	fi
    Sync;
	
}

WebUpdateComparisonAPPFile()
{
    Return=0;
    ComparisonMessage=`diff -r /app/ /mnt/SD/update/app/`;
    if [ "$ComparisonMessage" != "" ]; then
	Return=-1;
    fi
    expr $Return;
}

WebUpdateDeleteDecompressedFile()
{
    rm -rf /app.tar.gz;
    rm -rf /app/VPNClient;
}

DeleteWebRedundantFile()
{
    rm -rf /mnt/SD/update/command*.sh;
    rm -rf /mnt/SD/update/function.sh;
    rm -rf /mnt/SD/update/rotarySwitch.sh;
    rm -rf /mnt/SD/update/Environment;
    rm -rf /mnt/SD/update/app.tar.gz;
    rm -rf /mnt/SD/update/ua-arm64*.tar;

    rm -rf /ua-arm64*.tar;
    rm -rf /command*.sh;
    rm -rf /function.sh;
    rm -rf /Environment;
    rm -rf /app.tar.gz ;
    rm -rf /rotarySwitch.sh;

}

DeleteOldAPPFolder()
{
	rm -rf /app_old;
	Sync;
}

RenameFactoryFolder()
{
	rm -rf /mnt/SD/factory_old;
	mv /factory /mnt/SD/factory_old;
}

CreatFactoryEnvironment()
{
	mkdir /factory;
	cp /mnt/SD/update/ua-arm64*.tar /factory/.;
	if [ $? -ne 0 ]; then
	{
	  rm -rf /factory;
	  mv /mnt/SD/factory_old /factory;
	  WriteStringToWebLog "Step3: Update Factory Firmware Fail.";
	  Beep 4 0.25 0.1;
	}
	else
	WriteStringToWebLog "Step3: Update Factory Firmware Successful.";
	fi
	
}

DeleteOldFactoryFolder()
{
	rm -rf /mnt/SD/factory_old;
}

Beep()
{
  FREQ_Hz=$(awk -v x=$2 'BEGIN {printf "%d",1/x}')
  LEN_ms=$(awk -v x=$2 'BEGIN {printf "%d",x*1000}')
  DELAY_ms=$(awk -v x=$3 'BEGIN {printf "%d",x*1000}')
  for(( i=0; i<$1; i=i+1))
  do
     beep -f $FREQ_Hz -l $LEN_ms -r 1 -D $DELAY_ms
  done
}

ClearApp()
{
    killall "MainProgram.sh" >& /dev/null;
    killall "MainProgram" >& /dev/null;
    killall "mosquitto" >& /dev/null;
    killall "inadyn" >& /dev/null;
    killall "ua-backstageService" >& /dev/null;
    systemctl stop ua-runtime.service;
    systemctl stop ua-broker.service;
    systemctl stop ua-backstageService.service;
    systemctl stop ua-snmpd.service;
    systemctl stop ua-iftttConditionTrigger.service;
}

RemoveApp()
{
    rm -rf /app;
    find /lib/systemd/system/ua-* ! -name 'ua-rotarySwitch.service' -type f -exec rm -f {} +
}

RemoveFactory()
{
    rm -rf /factory;
}

CreateEnvironment()
{
    mkdir /factory;
    Sync;
}

UsbCheckTarFileName()
{
    Total=`ls -l /mnt/USB/*.tar  | grep "^-" | wc -l`;
    if [ "$Total" != "1" ]; then
        expr -1;
        return;
    fi
    
    Path="/mnt/USB/";
    TarName=`ls "$Path"ua-arm64*.tar`;
    if [ "$TarName" = "" ]; then
        expr 0;
        return;
    fi

    expr 1;
}


CheckTarFileName()
{
    Total=`ls -l /mnt/SD/*.tar  | grep "^-" | wc -l`;
    if [ "$Total" != "1" ]; then
        expr -1;
        return;
    fi
    
    Path="/mnt/SD/";
    TarName=`ls "$Path"ua-arm64*.tar`;
    if [ "$TarName" = "" ]; then
        expr 0;
        return;
    fi

    expr 1;
}

UsbCopyInstallFileToEnvironment()
{
    cp -rf /mnt/USB/ua-arm64*.tar /.;
    Sync;
    rm -rf /factory/*;
    cp -rf /mnt/USB/ua-arm64*.tar /factory;
    Sync;
}

CopyInstallFileToEnvironment()
{
    cp -rf /mnt/SD/ua-arm64*.tar /.;
    Sync;
    rm -rf /factory/*;
    cp -rf /mnt/SD/ua-arm64*.tar /factory;
    Sync;
}

CopyFactoryFileToEnvironment()
{
    cp -rf /factory/ua-arm64*.tar /.;
    Sync;
}

ComparisonFactoryTarFile()
{
    Return=0;
    TarName1=`ls /factory/*.tar`;
    TarName2=`ls /*.tar`;
    ComparisonMessage=`diff $TarName1 $TarName2`;
    if [ "$ComparisonMessage" != "" ]; then
	Return=-1;
    fi
    expr $Return;
}

UsbComparisonTarFile()
{
    Return=0;
    TarName1=`ls /mnt/USB/*.tar`;
    TarName2=`ls /*.tar`;
    ComparisonMessage=`diff $TarName1 $TarName2`;
    if [ "$ComparisonMessage" != "" ]; then
	Return=-1;
    fi
    expr $Return;
}

ComparisonTarFile()
{
    Return=0;
    TarName1=`ls /mnt/SD/*.tar`;
    TarName2=`ls /*.tar`;
    ComparisonMessage=`diff $TarName1 $TarName2`;
    if [ "$ComparisonMessage" != "" ]; then
	Return=-1;
    fi
    expr $Return;
}

DecompressedFile()
{
    tar --warning=no-timestamp -xf /ua-arm64*.tar -C /.;
    Sync;
    tar --warning=no-timestamp -zxf /app.tar.gz -C /.;
    Sync;
    
}
UsbCopyEnvironment()
{
#Common
    CopyCommonFile;
#Wireless
    #CopyWirelessFile;
}

CopyEnvironment()
{
#Common
    CopyCommonFile;
#Wireless
    #CopyWirelessFile;
}

CopyCommonFile()
{
	chmod 644 /Environment/Service/*.service;
    cp -rf /Environment/Service/*.service /lib/systemd/system/;
	
	cp -rf /rotarySwitch.sh /icpdas/init/;
   	chmod 755 /icpdas/init/rotarySwitch.sh >& /dev/null;
}

CopyWirelessFile()
{
    Wireless_3G=`lsusb -d 05c6:`;
    Wireless_4G=`lsusb -d 2c7c:`;
   
}

UsbSetEnvironment()
{
    systemctl enable ua-searchIP.service;
    systemctl enable ua-rotarySwitch.service;
    systemctl enable ua-runtime.service;
    systemctl enable ua-broker.service;
    systemctl enable ua-web.service;
    systemctl enable ua-iftttConditionTrigger.service;
    systemctl enable ua-daemon.service;
    systemctl enable ua-backstageService.service;
    systemctl enable ua-dynamic-blocklist.service;
}

SetEnvironment()
{
   
    systemctl enable ua-searchIP.service;
    systemctl enable ua-rotarySwitch.service;
    systemctl enable ua-runtime.service;
    systemctl enable ua-broker.service;
    systemctl enable ua-web.service;
    systemctl enable ua-iftttConditionTrigger.service;
    systemctl enable ua-daemon.service;
    systemctl enable ua-backstageService.service;
    systemctl enable ua-dynamic-blocklist.service;
    systemctl disable ua-ddns.service;
    systemctl disable ua-snmpd.service;
}

SetStaticIP()
{
    Return=0;
    _IP1=`ipv4set eth0 static 192.168.255.1 255.255.0.0 192.168.1.1 2>&1`;
    if [[ $_IP1 != *"applied successfully"* ]]; then
          Return=-1;
    fi
    _IP2=`ipv4set eth1 static 10.0.0.1 255.255.0.0 10.168.1.1 2>&1`;
    if [[ $_IP2 != *"applied successfully"* ]]; then
          Return=-1;
    fi
    expr $Return;
}

ChmodFile()
{
    chown -R root:root /app
    chmod 755 /app/* -R >& /dev/null;
    #chmod 755 /app/MQTT/Broker/* >& /dev/null;
    #chmod 755 /app/runtime/MainProgram >& /dev/null;
    #chmod 755 /rotarySwitch.sh >& /dev/null;
    #chmod 755 /app/SearchIP/* >& /dev/null;
    #chmod 755 /app/Web/* >& /dev/null;
    #chmod 755 /app/DBus/* >& /dev/null;
    #chmod 755 /app/ua-backstageService/bin/* >& /dev/null;
    #Wireless
    #chmod 755 /app/Wireless/* >& /dev/null;
    #chmod 755 /etc/ppp/ip-up.d/PPP0route >& /dev/null;
    #eeprom
    #chmod 755 /app/Eeprom/* >& /dev/null;
    #database
    #chmod 755 /app/MysqlConnecti/bin/* >& /dev/null;
    #chmod 755 /app/MySqlConnecti/bin/* >& /dev/null;

}

UsbDeleteResidualFile()
{
    rm -rf /mnt/USB/command*.sh;
    rm -rf /mnt/USB/function.sh;
    rm -rf /mnt/USB/rotarySwitch.sh;
    rm -rf /mnt/USB/RotarySwitch.sh;
    rm -rf /mnt/USB/Environment;
    rm -rf /mnt/USB/app.tar.gz;

    rm -rf /ua-arm64*.tar;
    rm -rf /command*.sh;
    rm -rf /function.sh;
    rm -rf /Environment;
    rm -rf /rotarySwitch.sh;
    rm -rf /RotarySwitch.sh;  
    rm -rf /app.tar.gz;
    rm -rf /app/VPNClient;

}

DeleteResidualFile()
{
    rm -rf /mnt/SD/command*.sh;
    rm -rf /mnt/SD/function.sh;
    rm -rf /mnt/SD/rotarySwitch.sh;
    rm -rf /mnt/SD/RotarySwitch.sh;
    rm -rf /mnt/SD/Environment;
    rm -rf /mnt/SD/app.tar.gz;

    rm -rf /ua-arm64*.tar;
    rm -rf /command*.sh;
    rm -rf /function.sh;
    rm -rf /Environment;
    rm -rf /rotarySwitch.sh;
    rm -rf /RotarySwitch.sh;  
    rm -rf /app.tar.gz;
    rm -rf /app/VPNClient;

}


DeleteFactoryResidualFile()
{
    rm -rf /factory/command*.sh;
    rm -rf /factory/function.sh;
    rm -rf /factory/rotarySwitch.sh;
    rm -rf /factory/RotarySwitch.sh;
    rm -rf /factory/Environment;
    rm -rf /factory/app.tar.gz;
 
    rm -rf /ua-arm64*.tar;
    rm -rf /command*.sh;
    rm -rf /function.sh;
    rm -rf /Environment;
    rm -rf /app.tar.gz ;
    rm -rf /rotarySwitch.sh;
    rm -rf /RotarySwitch.sh;     
    rm -rf /app/VPNClient;
}

Sync()
{
    sync;sync;sync;
}

ClearEeprom()
{
 
    /app/Eeprom/eep -w 0 "" -s >& /dev/null;

}

SetEeprom()
{
    #ClearEeprom;
    Message=$(date +%Y/%m/%d-%H:%M:%S)" $1";
    /app/Eeprom/eep -w 0 "$Message" -s;
}

Install_openvpn_if_needed() 
{
    # Check if OpenVPN is installed using dpkg
    if dpkg -l | grep -q openvpn
    then
        echo "OpenVPN is already installed."
    else
        echo "OpenVPN is not installed. Installing now..."

        # Define the package path
        PACKAGE_PATH="/app/VPNClient"

        # Define the packages to install in the correct order
        PACKAGES=(
            "libpkcs11-helper1_1.26-1_arm64.deb"                    # Install pkcs11-helper first
            "openvpn_2.4.12-0ubuntu0.20.04.2_arm64.deb"             # Install OpenVPN next
            "dpkg -i network-manager-openvpn_1.8.12-1_arm64.deb"    # Install network-manager-openvpn last
        )

        # Iterate over the packages and install them
        for PACKAGE in "${PACKAGES[@]}"
        do
            PACKAGE_FILE="$PACKAGE_PATH/$PACKAGE"
            if [ -f "$PACKAGE_FILE" ]; then
                 DEBIAN_FRONTEND=noninteractive dpkg -i "$PACKAGE_FILE"
            else
                echo "Package file $PACKAGE_FILE not found."
            fi
        done

        echo "OpenVPN and dependencies have been installed."
    fi
}

clear_openvpn_conf() 
{
    local OPENVPN_DIR="/etc/openvpn"
    #mkdir -p "$OPENVPN_DIR"
    find "$OPENVPN_DIR" -maxdepth 1 -type f -name "*.conf" -delete
    rm -rf "$OPENVPN_DIR/credentials"
}

ResetFirewall()
{
    ufw default allow incoming;
    echo "y" | ufw reset;
    echo "y" | ufw enable;
    rm -f /etc/ufw/*.rules.*
    rm -f /icpdas/whitelist/whitelist;
}

ShowStartInstall()
{
    printf "\E[0;32;40m";
    echo "########## Start Install ##########";
    printf "\E[0m";
}

ShowNetworkConnectionError()
{
    printf "\E[0;31;40m";
    echo "xxxxxxxxxx Please check your network connection xxxxxxxxxx";
    printf "\E[0m";
}

ShowCheckTarFileNameError()
{
    printf "\E[0;31;40m";
    echo "xxxxxxxxxx Check tar file name xxxxxxxxxx";
    printf "\E[0m";

}

ShowComparisonTarFileError()
{
    printf "\E[0;31;40m";
    echo "xxxxxxxxxx Comparison file error xxxxxxxxxx";
    printf "\E[0m";
}

ShowRuntimePackageError()
{
    printf "\E[0;31;40m";
    echo "xxxxxxxxxx Runtime package file is missing xxxxxxxxxx";
    printf "\E[0m";
}

ShowInstallSuccess()
{
    printf "\E[0;32;40m";
    echo "########## Install success ##########";
    printf "\E[0m";
  
}

ChangeComPortDeviceSetting()
{
    printf "\E[0;32;40m";
    echo "########## Install success ##########";
    printf "\E[0m";
}


# ===== 重啟設定：升級遷移 / 工廠還原清除（不自動觸發，由各更新流程在 command 裡呼叫）=====

# 升級時呼叫：把舊版(ua-restart-hourly)或壞掉(script 路徑被清)的重啟設定，重建/對齊到新標準
# ua-runtime-restart，保留客戶已設的間隔/阈值。冪等，多跑無害。
MigrateRestartUnit()
{
    SYSD=/etc/systemd/system
    NEW=ua-runtime-restart
    SCRIPT=/icpdas/ua-runtime-restart/check_runtime_tcp.sh
    CHANGED=0
    TARGET=ua-runtime.service

    # (1) 舊版 ua-restart-hourly(只有定時重啟、無 monitor) -> 轉等價的 ua-runtime-restart schedule
    if [ -e "$SYSD/ua-restart-hourly.timer" ] || [ -e "$SYSD/ua-restart-hourly.service" ]; then
        if [ ! -e "$SYSD/$NEW.timer" ]; then          # 還沒新 unit 才轉，不蓋客戶在新版設過的
            IV=$(grep -hoE 'On(Unit)?ActiveSec=[0-9]+h' "$SYSD/ua-restart-hourly.timer" 2>/dev/null | grep -oE '[0-9]+' | head -1)
            [ -z "$IV" ] && IV=4
            _WriteRestartScheduleUnit "$IV"
        fi
        systemctl stop ua-restart-hourly.timer    >/dev/null 2>&1
        systemctl disable ua-restart-hourly.timer >/dev/null 2>&1
        systemctl stop ua-restart-hourly.service  >/dev/null 2>&1
        rm -f "$SYSD/ua-restart-hourly.timer" "$SYSD/ua-restart-hourly.service"
        CHANGED=1
    fi

    # (2) ua-runtime-restart 是 monitor 但 script 在舊路徑(/app)被韌體更新清掉 -> 重生 script 到 /icpdas、
    #     修正 ExecStart；阈值在 service Environment、間隔在 timer，都不動 -> 設定保留
    if [ -e "$SYSD/$NEW.service" ]; then
        ES=$(grep -oE '/[^ "]+\.sh' "$SYSD/$NEW.service" 2>/dev/null | head -1)
        if [ -n "$ES" ] && [ ! -e "$ES" ]; then
            _WriteRestartCheckScript
            sed -i "s#ExecStart=[^ ]*\.sh#ExecStart=$SCRIPT#" "$SYSD/$NEW.service"
            CHANGED=1
        fi
    fi

    # 只在 (1)/(2) 真的改了才生效 + 重啟 timer
    if [ "$CHANGED" = "1" ]; then
        systemctl daemon-reload
        [ -e "$SYSD/$NEW.timer" ] && { systemctl enable $NEW.timer >/dev/null 2>&1; systemctl restart $NEW.timer >/dev/null 2>&1; }
    fi
}

# 工廠還原時呼叫：清掉所有重啟設定(新舊都清) + script 目錄，回出廠。
ClearRestartUnit()
{
    SYSD=/etc/systemd/system
    for u in ua-runtime-restart ua-restart-hourly; do
        systemctl stop    $u.timer   >/dev/null 2>&1
        systemctl disable $u.timer   >/dev/null 2>&1
        systemctl stop    $u.service >/dev/null 2>&1
        rm -f "$SYSD/$u.timer" "$SYSD/$u.service"
    done
    rm -rf /icpdas/ua-runtime-restart
    systemctl daemon-reload
    systemctl reset-failed >/dev/null 2>&1
}

# helper：寫跟後端 _SetRestartServiceSetting_ 一致的 schedule unit
_WriteRestartScheduleUnit()
{
    IV=$1
    cat > /etc/systemd/system/ua-runtime-restart.service <<UNIT
[Unit]
Description=Restart $TARGET on schedule
After=network.target

[Service]
Type=oneshot
ExecStart=/bin/bash -c "/bin/systemctl is-active --quiet $TARGET && /bin/systemctl restart $TARGET || true"

[Install]
WantedBy=multi-user.target
UNIT
    cat > /etc/systemd/system/ua-runtime-restart.timer <<UNIT
[Unit]
Description=Timer for ua-runtime-restart (every $IV hour(s))

[Timer]
Unit=ua-runtime-restart.service
OnActiveSec=${IV}h
OnUnitActiveSec=${IV}h
RandomizedDelaySec=10
AccuracySec=1s

[Install]
WantedBy=timers.target
UNIT
}

# helper：重生健康檢查 script(內容與後端 scriptContent 一致)
_WriteRestartCheckScript()
{
    mkdir -p /icpdas/ua-runtime-restart
    cat > /icpdas/ua-runtime-restart/check_runtime_tcp.sh <<'CHK'
#!/bin/bash
# Auto-generated by RuntimeRestartSetting (mode=monitor). Do not edit by hand.
: "${CW_THRESHOLD:=50}"
: "${SR_THRESHOLD:=30}"
[ -z "$TARGET_SERVICE" ] && exit 0

PID=$(pgrep -x MainProgram | head -n1)
[ -z "$PID" ] && exit 0

SS_OUT=$(ss -ntp state close-wait state syn-recv 2>/dev/null)
CW=$(echo "$SS_OUT" | grep CLOSE-WAIT | grep -cE "(,|pid=)$PID,")
SR=$(echo "$SS_OUT" | grep SYN-RECV   | grep -cE "(,|pid=)$PID,")

if [ "$CW" -gt "$CW_THRESHOLD" ] || [ "$SR" -gt "$SR_THRESHOLD" ]; then
    if /bin/systemctl is-active --quiet "$TARGET_SERVICE"; then
        /bin/systemctl restart "$TARGET_SERVICE"
        logger -t ua-runtime-restart "restarted $TARGET_SERVICE (CW=$CW/$CW_THRESHOLD SR=$SR/$SR_THRESHOLD PID=$PID)"
    fi
fi
exit 0
CHK
    chmod 755 /icpdas/ua-runtime-restart/check_runtime_tcp.sh
}

