package atservice

import (
	"errors"
	"netease_control_center/interfaces/log"
	"netease_control_center/modules/hardware/mcu_leds/serial"
	"time"
)

const (
	MCU_BOOT_C_CHAR_CNT = 3
	MCU_BOOT_U_CHAR_CNT = 3
)

var (
	sPort          *serial.Port
	mcuBootcharCnt int         = 0
	McuBootMode    bool        = false
	sendUcharCnt   int         = 0
	sendUCharTimer *time.Timer = nil //设置mcu是否勾住的timer，如果没勾住，那么重启再发
)

func uartReadStart() {
	buf := make([]byte, 128)
	for {
		if McuBootMode {
			log.Println(log.ErrorLog, "McuBootMode = 1, break...")
			break
		}
		n, err := sPort.Read(buf)
		if err != nil {
			log.Println(log.ErrorLog, err)
		} else {
			uartDataRev(buf[:n])
		}
	}
}

func uartRead1byte() (byte, error) {
	buf := make([]byte, 1)
	_, err := sPort.Read(buf)
	if err != nil {
		log.Println(log.ErrorLog, err)
		return 0, err
	} else {
		return buf[0], nil
	}
}

func uartInit() error {
	c := &serial.Config{Name: "/dev/ttyS2", Baud: 1500000, FlowCtrl: serial.HWCONTROL_RTS_CTS}
	var err error
	sPort, err = serial.OpenPort(c)
	if err != nil {
		log.Println(log.ErrorLog, err)
		return errors.New("port open error!")
	} else {
		flushUart() //flush uart data
		sPort.Close()
		sPort, err = serial.OpenPort(c)
		if err != nil {
			log.Println(log.ErrorLog, err)
			return errors.New("port open error!")
		} else {
			flushUart() //flush uart data
			go uartReadStart()
		}
	}

	return err
}

func uartWrite(buf []byte) error {
	if sPort == nil {
		return errors.New("port not open!")
	}
	_, err := sPort.Write(buf)
	if err != nil {
		log.Println(log.ErrorLog, err)
	}

	return err
}

//rev uart data
func uartDataRev(buf []byte) {
	if mcuOTAMode {
		if sendUCharTimer != nil {
			sendUCharTimer.Stop()
			sendUCharTimer = nil
		}
		log.Println(log.DebugLog, "rev data: ", buf)
		if len(buf) >= 1 && buf[len(buf)-1] == 'C' {
			mcuBootcharCnt++
			sendUcharCnt = 0
			if mcuBootcharCnt >= MCU_BOOT_C_CHAR_CNT {
				McuBootMode = true
				mcuBootcharCnt = 0
				log.Println(log.DebugLog, "MCU OTA file: ", mcuImagePath)
				otaStart(mcuImagePath)
				McuBootMode = false
				mcuBootcharCnt = 0
				ignoreAtGpioInt = false //此处跳转到image，不需要忽略at gpio 中断
				otaFinish()
				go uartReadStart()
			}
		} else {
			log.Println(log.WarningLog, "atCmdMode = ", atCmdMode)
			if atCmdMode == false {
				sendUcharCnt++
				if sendUcharCnt <= MCU_BOOT_U_CHAR_CNT {
					forceMcuOtaUpdateStart(0)
				} else {
					log.Println(log.WarningLog, "maybe mcu boot err")
					if AtReadyCb != nil {
						AtReadyCb(MCU_STATUS_BOOT_ERR)
					}
				}
			}
		}
	} else {
		//log.Printf(log.DebugLog, "rev:%x\n", buf)
		atDataRev(buf)
	}
}

func forceMcuOtaUpdateStart(d time.Duration) {
	if d == 0 {
		sendUchar2Mcu()
	} else {
		time.AfterFunc(d, func() {
			sendUchar2Mcu()
		})
	}
}

func sendUchar2Mcu() {
	if !McuBootMode {
		if sendUCharTimer != nil {
			sendUCharTimer.Stop()
			log.Println(log.DebugLog, "sendUCharTimer,   Stop...")
		}
		sendUCharTimer = time.AfterFunc(5*time.Second, func() {
			log.Println(log.DebugLog, "sendUCharTimer,   ResetMCU...")
			ResetMCU()
		})
		uartWrite([]byte{'U'})
		log.Println(log.WarningLog, "send U char to mcu")
	}
}

func flushUart() error {
	if sPort == nil {
		return errors.New("port not open!")
	}
	err := sPort.Flush()
	if err != nil {
		log.Println(log.ErrorLog, err)
	}

	log.Println(log.WarningLog, "flash the uart.................")

	return err
}
