package main

import (
	"fmt"
	"os"
	"strings"
	"time"

	gps "hnyfkj.com.cn/rtu/linux/air530z"
	baseapp "hnyfkj.com.cn/rtu/linux/baseapp"
	camera1 "hnyfkj.com.cn/rtu/linux/camera"
	netmgrd "hnyfkj.com.cn/rtu/linux/netmgrd"
)

const (
	rcLocalTxt = `
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

#设置系统主频
echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
echo 528000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed

#设置一秒落盘(是低功耗产品时, RTU数据板可能随时掉电, 长供电产品, 不需要设置)
#echo 100 > /proc/sys/vm/dirty_writeback_centisecs
#echo 100 > /proc/sys/vm/dirty_expire_centisecs

#启动运行程序
/home/root/rtu_linux_modules/script/stop
/home/root/rtu_linux_modules/script/start

exit 0
`
	rcLocalFile = "/etc/rc.local"
)

func enableAutoStartOnBoot() error {
	if _, err := os.Stat(rcLocalFile); err == nil {
		bakFile := rcLocalFile + "." + time.Now().Format("20060102150405")
		err = os.Rename(rcLocalFile, bakFile)
		if err != nil {
			return err
		}
	}

	f, err := os.OpenFile(rcLocalFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = f.WriteString(rcLocalTxt)
	if err != nil {
		return err
	}

	err = os.Chmod(rcLocalFile, 0755)
	if err != nil {
		return err
	}

	return nil
}

func main() {
	if baseapp.IsArgsParam("-h") {
		help()
		return
	}

	if baseapp.IsArgsParam("-v") {
		fmt.Println("程序版本:", baseapp.Version, "\n构建时间:", baseapp.BuildTime)
		return
	}

	if baseapp.GetArgsParamStr("-install", "") == "boot" {
		err := enableAutoStartOnBoot()
		if err != nil {
			fmt.Printf("设置开机自启动失败: %v\n", err)
		} else {
			fmt.Println("设置开机自启动成功")
		}
		return
	}

	baseapp.ModuleInit()
	baseapp.SingleInstanceRun() // 异步非阻塞
	baseapp.Logger.Infof("程序版本: %s 构建时间: %s\n程序开始运行...",
		baseapp.Version, baseapp.BuildTime)

	// 01, 初始化卫星定位模块
	gps.ModuleInit()

	// 02, 初始化4G调制解调器
	if !netmgrd.ModemInit() {
		goto end_p
	}
	go writeDeviceIMEI() // 异步获取IMEI号并写入文件, 用于YFKJ SSHD远程运维服务的设备标识

	// 03, 初始化网络管理模块
	netmgrd.ModuleInit()
	netmgrd.WaitAllOK(time.Duration(30) * time.Second) // 等待联网成功和NTP时间同步成功

	// 04, 初始化相机拍照模块
	if !camera1.ModuleInit(false, "192.168.100.1/24", "192.168.100.100/24") {
		goto end_p
	}

	// 05, 初始化与控制板通信, Todo: 根据项目不同, 使用的控制版硬件和协议都不同, 具体看情况

	// 06, 后台服务器业务交互, Todo: 根据项目不同, 实现具体的业务逻辑协议都不同, 具体看情况

	// 07, 阻塞等待退出信号量
	<-baseapp.IsExit2()

	// 08, 退出程序并释放资源
end_p:
	netmgrd.ModemExit()
	gps.ModuleExit()

	baseapp.Logger.Info("程序退出")
	baseapp.ExitLogger() // 安全的关闭日志模块
	baseapp.SafeExit()   // 安全的关闭退出程序
}

func help() {
	h := `
-h 显示帮助提示
-v 当前程序版本
-install boot 设置程序开机自启动
`

	fmt.Println(h)
}

func writeDeviceIMEI() {
	const path = "/var/device_imei.txt"
	tmp := path + ".tmp"

	for {
		imei := strings.TrimSpace(netmgrd.GetIMEI())
		if imei == "" || imei == netmgrd.ErrUnknownModemTypeMsg {
			time.Sleep(time.Second)
			continue
		}

		if old, err := os.ReadFile(path); err == nil && strings.TrimSpace(string(old)) == imei {
			return
		}

		if os.WriteFile(tmp, []byte(imei+"\n"), 0644) == nil {
			_ = os.Rename(tmp, path)
		}
		return
	}
}
