package FLXCheckInController
import (
	"encoding/hex"
	"flx/Common"
	FLXDevice "flx/Device"
	"fmt"
	"io"
	"time"
	log "github.com/sirupsen/logrus"
	serial "github.com/tarm/goserial"
)
type FlxCheckInDeviceController struct {
	FirstRun                 bool
	IsRunning                bool
	IsOpen                   bool
	IsOnline                 bool
	OldSData                 string
	SerialPort               *io.ReadWriteCloser
	Reader                   FlxCheckInCmdReader
	Sender                   FlxCheckInCmdSender
	ComPackets               chan []byte
	previousBuffer           []byte
	HasDataIsReturned        bool
	deviceGUID               string
	regsterEvent_SeatInfos   []FLXDevice.SeatChangeEventArg
	DataReciveSave           []string
	InvokeDeviceEventHandler func(FLXDevice.EventArgSource, FLXDevice.EventArgType, []FLXDevice.SeatChangeEventArg)
}
func (para *FlxCheckInDeviceController) FlxCheckInDeviceController() {
	defer func() {
		if r := recover(); r != nil {
			log.Error("FlxCheckInDeviceController:", r)
		}
	}()
	para.InitControllerBusnissInfo()
}
func (para *FlxCheckInDeviceController) InitControllerBusnissInfo() {
	defer func() {
		if r := recover(); r != nil {
			log.Error("InitControllerBusnissInfo:", r)
		}
	}()
	para.ComPackets = make(chan []byte, 600)
	para.Sender.init(para.SerialPort)
	// Sender.defualtDelayed = configKeys.OneTimeDataPackedDelayed;
	// Sender.OnDataSendLogHandler += Sender_OnDataSendLogHandler;
	para.Reader.InitPara(para.SerialPort)
	para.Reader.InvokeOnBusinessDataReviceData = para.Reader_OnDataReciveEventHandler
	para.Reader.OnConnectStatusHandler = para.Reader_OnConnectStatusHandler
}
func (para *FlxCheckInDeviceController) Reader_OnConnectStatusHandler(dtLastRecived time.Time) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("Reader_OnConnectStatusHandler:", r)
		}
	}()
	ts := time.Now().Sub(dtLastRecived)
	//判断报到机是否已达3秒没有向上位机发送数据
	if ts.Seconds() >= 3 {
		//尝试获取报到机系统信息,如果报到机无数据返回,视为离线,否则,作在线处理
		para.Sender.SendHeartBeat()
		revBuffer := para.Reader.ReadResponseData()
		if revBuffer == nil {
			if para.IsOnline {
				para.IsOnline = false
			}
		} else {
			para.Reader.dtLastRecivedDateTime = time.Now()
			if !para.IsOnline {
				if para.FirstRun {
					para.FirstRun = false
				} else {
					//发送蜂鸣指令
					para.Sender.SendBeep(1)
				}
				para.IsOnline = true
			}
		}
	}
}
// / 
// /D7-D6:表示控制蜂鸣器操作模式
// /00:表示不对蜂鸣器进行控制操作
// /01:表示有人通过即提示
// /10:表示有人无卡提示
// /11:表示有人有卡提示
// /D5-D4:表示控制灯的操作模式
// /00:表示不对灯进行控制操作
// /01:表示有人通过即提示
// /10:表示有人无卡提示
// /11:表示有人有卡提示
// /D3-D0:表示时钟周期
// / 
func (para *FlxCheckInDeviceController) InitEStatus() byte {
	defer func() {
		if r := recover(); r != nil {
			log.Error("InitEStatus:", r)
		}
	}()
	var eTmp byte = 0
	eTmp += 0xC0
	eTmp += 0x30
	return eTmp
}
// func Sender_OnDataSendLogHandler(string logMessage)	{
// 	RequestDebugMessage(this, logMessage);
// }
// func Reader_OnDataReciveLogHandler(string logMessage)	{
// 	RequestDebugMessage(this, logMessage);
// }
func (para *FlxCheckInDeviceController) OpenDevice() bool {
	defer func() {
		if r := recover(); r != nil {
			log.Error("OpenDevice:", r)
		}
	}()
	// getCommlist2()
	// c := &serial.Config{Name: "COM3", Baud: 19200}
	// s, err := serial.OpenPort(c)
	// if err != nil {
	// 	fmt.Println(err)
	// }
	// n, err := s.Write([]byte("012345"))
	// if err != nil {
	// 	fmt.Println(err)
	// }
	// fmt.Printf("Read %d Bytes\r\n", n)
	cfig := Common.LoadConfig()
	c := &serial.Config{Name: cfig.CheckInDoor.PortName, Baud: cfig.CheckInDoor.BaudRate}
	// var err error
	fmt.Println("enterging OpenDevice ")
	cport, err := serial.OpenPort(c)
	if err != nil {
		fmt.Println("打开串口驱动报错:")
		fmt.Println(err)
		return false
	} else {
		para.IsOpen = true
	}
	para.SerialPort = &cport
	para.Sender.init(para.SerialPort)
	para.Reader.InitPara(para.SerialPort)
	para.Sender.InitDoor()
	// para.Sender.SendBeep(1)
	// if nil != para.Reader.ReadResponseData() {
	para.Sender.DownLoadEStatus(para.InitEStatus())
	para.Sender.SendBeep(1)
	para.Reader.Start()
	time.Sleep(500)
	para.CreatEventHandleThread()
	fmt.Println(OpenSerialPort_Success)
	return true
	// }
	// fmt.Println(ReciveDataFromCOM_Error)
	// return false
}
func (para *FlxCheckInDeviceController) CloseDevice() bool {
	defer func() {
		if r := recover(); r != nil {
			log.Error("CloseDevice:", r)
		}
	}()
	if para.IsOpen {
		para.Sender.SendBeep(1)
		para.Reader.Stop()
		time.Sleep(20 * time.Millisecond)
		para.KillEventHandleThread()
		// (*para.SerialPort).Close()
		if err := (*para.SerialPort).Close(); err != nil {
			fmt.Println(CloseSerialPort_Faild, ":", err)
			return false
		}
	}
	para.IsOpen = false
	if !para.IsOpen {
		fmt.Println(CloseSerialPort_Success)
		return true
	} else {
		fmt.Println(CloseSerialPort_Faild)
		return false
	}
}
func (para *FlxCheckInDeviceController) CheckInStartAll() {
	defer func() {
		if r := recover(); r != nil {
			log.Error("CheckInStartAll:", r)
		}
	}()
	if !para.IsOpen {
		para.OpenDevice()
	}
}
func (para *FlxCheckInDeviceController) CheckInStopAll() {
	defer func() {
		if r := recover(); r != nil {
			log.Error("CheckInStopAll:", r)
		}
	}()
	para.CloseDevice()
}
func (para *FlxCheckInDeviceController) StartCardReadIn() {
	defer func() {
		if r := recover(); r != nil {
			log.Error("StartCardReadIn:", r)
		}
	}()
	para.Reader.Start()
	time.Sleep(5 * time.Microsecond)
	para.CreatEventHandleThread()
}
func (para *FlxCheckInDeviceController) StopCardReadIn() {
	defer func() {
		if r := recover(); r != nil {
			log.Error("StopCardReadIn:", r)
		}
	}()
	para.Reader.Stop()
	time.Sleep(500)
	para.KillEventHandleThread()
}
func (para *FlxCheckInDeviceController) BeepOn(msec int) bool {
	defer func() {
		if r := recover(); r != nil {
			log.Error("BeepOn:", r)
		}
	}()
	var bRetValue bool = false
	if para.IsOpen {
		//Sender.SendAlarm(msec);
		for index := 0; index < msec; index++ {
			para.Sender.SendAlarm(1)
			time.Sleep(1 * time.Microsecond)
		}
		bRetValue = true
	}
	return bRetValue
	//return true;
}
func (para *FlxCheckInDeviceController) BeepOff() bool {
	defer func() {
		if r := recover(); r != nil {
			log.Error("BeepOff:", r)
		}
	}()
	return true
}
func (para *FlxCheckInDeviceController) LightOn() bool {
	defer func() {
		if r := recover(); r != nil {
			log.Error("LightOn:", r)
		}
	}()
	return true
}
func (para *FlxCheckInDeviceController) LightOff() bool {
	defer func() {
		if r := recover(); r != nil {
			log.Error("LightOff:", r)
		}
	}()
	return true
}
func (para *FlxCheckInDeviceController) Reader_OnDataReciveEventHandler(compacket []byte) {
	defer func() {
		if r := recover(); r != nil {
			log.Error("Reader_OnDataReciveEventHandler:", r)
		}
	}()
	fmt.Println(compacket)
	for i := 0; i < len(para.DataReciveSave); i++ {
		if para.DataReciveSave[i] == string(compacket) {
			//避免返回相同卡号
			return
		}
	}
	para.DataReciveSave = append(para.DataReciveSave, string(compacket))
	para.HasDataIsReturned = true
	if compacket != nil && len(compacket) > 5 {
		if compacket[0] == CMD_HEAD && compacket[len(compacket)-1] == CMD_Tail {
			para.ComPackets <- compacket
		}
	}
	go func() {
		time.Sleep(time.Second * 5)
		para.DataReciveSave = para.DataReciveSave[1:]
	}()
}
// / 消息队列
func (para *FlxCheckInDeviceController) TimerCallbackHandler() {
	defer func() {
		if r := recover(); r != nil {
			log.Error("TimerCallbackHandler:", r)
		}
	}()
	for para.IsRunning {
		para.regsterEvent_SeatInfos = para.regsterEvent_SeatInfos[0:0]
		comPacket := <-para.ComPackets
		if para.OldSData == hex.EncodeToString(comPacket) {
			continue
		}
		var seatInfo FLXDevice.SeatChangeEventArg
		if len(comPacket) > 2 {
			seatInfo.DeviceGUID = para.deviceGUID
			switch comPacket[1] {
			case Read_Reader_State:
				seatInfo.EventValue = FLXDevice.EventArgValue_RegistrStatus
				seatInfo.Value_ExtraInt = int(comPacket[2])
				para.InvokeDeviceEventHandler(FLXDevice.EventArgSource_SivtChecker, FLXDevice.EventArgType_DeviceQueryEvent, []FLXDevice.SeatChangeEventArg{seatInfo})
			case Read_SeriaNo:
				if !EqualsByteArray(para.previousBuffer, comPacket) {
					if comPacket[2] != 2 && comPacket[2] != 1 {
						para.previousBuffer = comPacket
						// Console.WriteLine("1赋值" + DeviceUtil.ByteArrayToString(previousBuffer, 0, previousBuffer.Length))
						// Console.WriteLine("1    " + DeviceUtil.ByteArrayToString(comPacket, 0, comPacket.Length))
					}
					// var cardNo string
					// for i := 3; i < len(comPacket)-1; i++ {
					// 	cardNo += comPacket[i].ToString("X2")
					// }
					cardNo := hex.EncodeToString(comPacket[3:])
					seatInfo.EventValue = FLXDevice.EventArgValue_Register //不论进出检测到卡即为报到。
					switch comPacket[2] {
					case 2:
						seatInfo.Value_ExtraInt = CheckInDirection_Out
					case 1:
						seatInfo.Value_ExtraInt = CheckInDirection_In
					default:
						seatInfo.Value_ExtraInt = CheckInDirection_In
					}
					seatInfo.Value_ExtraStr = cardNo
					var isExist bool = false
					for _, arg := range para.regsterEvent_SeatInfos {
						if arg.Value_ExtraStr == seatInfo.Value_ExtraStr {
							isExist = true
							break
						}
					}
					if !isExist {
						para.regsterEvent_SeatInfos = append(para.regsterEvent_SeatInfos, seatInfo)
					}
					fmt.Println(InvokeCaredNo_Processed)
				}
			case Read_In_State:
				if !EqualsByteArray(para.previousBuffer, comPacket) {
					seatInfo.EventValue = FLXDevice.EventArgValue_Register //不论进出检测到卡即为报到。
					switch comPacket[2] {
					case 2:
						seatInfo.Value_ExtraInt = CheckInDirection_Out
					case 1:
						seatInfo.Value_ExtraInt = CheckInDirection_In
					default:
						seatInfo.Value_ExtraInt = CheckInDirection_Unkown
					}
					seatInfo.Value_ExtraStr = ""
					para.regsterEvent_SeatInfos = append(para.regsterEvent_SeatInfos, seatInfo)
					fmt.Println(InvokeCaredNo_Processed)
				}
			}
		}
		if seatInfo.Value_ExtraInt != 2 && seatInfo.Value_ExtraInt != 1 {
			para.previousBuffer = comPacket
			// Console.WriteLine("2赋值" + DeviceUtil.ByteArrayToString(previousBuffer, 0, previousBuffer.Length))
			// Console.WriteLine("2    " + DeviceUtil.ByteArrayToString(comPacket, 0, comPacket.Length))
		}
		if len(para.regsterEvent_SeatInfos) > 0 {
			// Console.WriteLine("触发事件" + regsterEvent_SeatInfos.Count + "个数据")
			para.InvokeDeviceEventHandler(FLXDevice.EventArgSource_SivtChecker, FLXDevice.EventArgType_RegisterEvent, para.regsterEvent_SeatInfos)
		}
	}
}
func EqualsByteArray(sorBuf []byte, argBuf []byte) bool {
	defer func() {
		if r := recover(); r != nil {
			log.Error("EqualsByteArray:", r)
		}
	}()
	if len(sorBuf) != len(argBuf) {
		return false
	} else {
		for i := 0; i < len(sorBuf); i++ {
			if sorBuf[i] != argBuf[i] {
				return false
			}
		}
	}
	return true
}
func (para *FlxCheckInDeviceController) CreatEventHandleThread() bool {
	defer func() {
		if r := recover(); r != nil {
			log.Error("CreatEventHandleThread:", r)
		}
	}()
	para.IsRunning = true
	go para.TimerCallbackHandler()
	fmt.Println("串口创建线程:" + CreateThread)
	return true
}
func (para *FlxCheckInDeviceController) KillEventHandleThread() bool {
	defer func() {
		if r := recover(); r != nil {
			log.Error("KillEventHandleThread:", r)
		}
	}()
	para.IsRunning = false
	fmt.Println("串口消毁线程:" + ClosedThread)
	return true
}