// Author: NiuJiuRu
// Email: niujiuru@qq.com

package air720u

import (
	"os"
	"sync"
	"time"

	"hnyfkj.com.cn/rtu/linux/baseapp"
)

const MODULE_NAME = "Air720U"

var (
	imei  string // Air720U模块的IMEI号, 唯一标识
	rssi  string // Air720U模块当前信号强度(RSSI)
	iccid string // Air720U模块插入SIM卡的ICCID号

	mu1, mu2, mu3          sync.Mutex
	isRunning1, isRunning2 bool
	exitCh1, exitCh2       chan struct{}
	wg1, wg2               sync.WaitGroup
)

// 初始化4G网络模块
func ModuleInit(bForceRepower bool /*是否强制重启*/) bool {
	mu1.Lock()
	defer mu1.Unlock()

	if isRunning1 {
		return true
	}

	var err error
	var ret int
	var bExists, bReady bool

	_, statErr := os.Stat("/dev/ttyUSB0")
	bExists = (statErr == nil)

	if bExists && !bForceRepower {
		ret, err = air720U_ComInit()
		if err == nil {
			goto openOK
		}
		switch ret {
		case -1, -3: // -1: 串口被占用或不存在(驱动有问题时)
			// -3: 设备无应答(初始化时会发送的单条关键配置指令)
			if ret == -1 {
				freeTTYUSB0()
			}
			air720U_Repower() // 重新上电
			bExists = false   // 等待复位, 标记设备已不存在
		case -99: // 模块型号不匹配, 不是合宙的 "Air720U"
			return false
		}
	} else { // 设备不存在, 或调用该函数时明确要求强制重启/
		air720U_Repower() //// 重新上电
		bExists = false   //// 等待复位, 标记设备已不存在
	}

	for range 6 {
		if baseapp.IsExit1() {
			return false
		}
		if !bExists {
			time.Sleep(5 * time.Second) // 等待设备文件再次出现
		}
		ret, err = air720U_ComInit()
		if err != nil && ret == -1 && !bExists { // 继续等待
			continue
		}
		break
	}

	if err != nil {
		baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
		return false
	}

openOK:
	imei, err = air720U_GetIMEI()
	if err != nil {
		air720U_ComExit()
		baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
		return false
	}
	baseapp.Logger.Infof("[%s] 模块IMEI: %s", MODULE_NAME, imei)

	bReady, _ = air720U_IsSimCardReady()
	baseapp.Logger.Infof("[%s] SIM卡状态: %v", MODULE_NAME, bReady)

	if !bReady {
		goto initOK
	}

	for range 30 { // 等待模块完成蜂窝网络注册, 否则RSSI读取不到, 网也不可能不去
		if baseapp.IsExit1() {
			air720U_ComExit()
			return false
		}
		cs, err := air720U_GetCregState()
		if err != nil || cs == 1 /*已注册本地网*/ || cs == 5 /*已注册漫游网*/ {
			break
		}
		time.Sleep(1 * time.Second)
	}

	rssi, err = air720U_GetRSSIFromCSQ()
	if err != nil {
		air720U_ComExit()
		baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
		return false
	}
	baseapp.Logger.Infof("[%s] 模块RSSI: %s", MODULE_NAME, rssi)

	iccid, err = air720U_GetSimICCID()
	if err != nil {
		air720U_ComExit()
		baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
		return false
	}
	baseapp.Logger.Infof("[%s] SIM卡ICCID: %s", MODULE_NAME, iccid)

initOK:
	exitCh1 = make(chan struct{})
	wg1.Add(1)
	go func() { // 启动携程循环读取4G模块的信号强度和ICCID号等信息
		defer wg1.Done()
		monitorAir720UInfo(exitCh1)
	}()

	isRunning1 = true
	return isRunning1
}

// 4G调制解调器退出
func ModuleExit() {
	mu1.Lock()
	defer mu1.Unlock()

	if !isRunning1 {
		return
	}

	close(exitCh1)
	wg1.Wait() // 等待循环读取4G模块的信号强度和ICCID号等信息的携程退出

	air720U_ComExit()
	imei, rssi, iccid = "", "", ""
	isRunning1 = false
}

// 获取模块的标识号
func GetIMEI() string {
	mu2.Lock()
	defer mu2.Unlock()
	return imei
}

// 获取当前信号强度
func GetRSSI() string {
	mu2.Lock()
	defer mu2.Unlock()
	return rssi
}

// 获取电话卡标识号
func GetSimICCID() string {
	mu2.Lock()
	defer mu2.Unlock()
	return iccid
}

// 循环读取刷新信息
func monitorAir720UInfo(exitCh <-chan struct{}) {
	t := time.NewTicker(time.Duration(5) * time.Second)
	defer t.Stop()
	for {
		select {
		case <-t.C:
			mu2.Lock()
			rssi, _ = air720U_GetRSSIFromCSQ()
			if bOK, _ := air720U_IsSimCardReady(); bOK {
				iccid, _ = air720U_GetSimICCID()
			} else {
				iccid = ""
			}
			mu2.Unlock()
		case <-exitCh:
			return
		} // select end
	} // for end
}

// 打开连接到4G网络
func Start4GNetwork() bool {
	mu3.Lock()
	defer mu3.Unlock()

	if isRunning2 {
		return true
	}

	killAllUdhcpc()
	err := disableEth0()
	if err != nil {
		baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
		return false
	}

	bExists, _ := udhcpcEth2Exists()
	if bExists {
		killEth2Udhcpc()
	}

	err = dialupEth2()
	if err != nil {
		baseapp.Logger.Errorf("[%s] 拨号连接\"eth2\"时发生错误: %v!!", MODULE_NAME, err)
		return false
	}
	ipv4, mask, err := getEth2Addr()
	if err != nil {
		baseapp.Logger.Errorf("[%s] 读取\"eth2\"地址时发生错误: %v!!", MODULE_NAME, err)
		return false
	}
	baseapp.Logger.Infof("[%s] \"eth2\"分配的地址: %s/%s", MODULE_NAME, ipv4, mask)

	exitCh2 = make(chan struct{})
	wg2.Add(1)
	go func() { // 启动携程守护"eth2"网卡上的 "udhcpc"后台服务进程
		defer wg2.Done()
		monitorEth2Udhcpc(exitCh2)
	}()

	isRunning2 = true
	return isRunning2
}

// 从4G网络断开连接
func Stop4GNetwork() {
	mu3.Lock()
	defer mu3.Unlock()

	if !isRunning2 {
		return
	}

	close(exitCh2)
	wg2.Wait() // 等待守护"eth2"网卡上的 "udhcpc"后台服务进程的携程退出

	bExists, _ := udhcpcEth2Exists()
	if bExists {
		killEth2Udhcpc()
	}

	isRunning2 = false
}
