package main

import (
	"sync"

	"github.com/sirupsen/logrus"

	"lc/common/protocol"
)

type ModelInfo struct {
	TID  uint16
	Flag int
}

type Device interface {
	Start()
	Stop()
	UpdateInfo(devinfo protocol.DevInfo)
	GetDevInfo() *protocol.DevInfo
	UpdateModel(tid uint16, flag int)
}

func CreateDevice(t uint8, devinfo *protocol.DevInfo) Device {
	var device Device
	switch t {
	case 0:
		device = NewModbusRtu(devinfo)
	case 1:
		device = NewConcentrator(devinfo)
	case 2:
		device = NewYmLampController(devinfo)
	default:
		logrus.Errorf("AddDevices:不支持的协议的设备:mode=%d", t)
	}
	return device
}

var _onceGetDeviceMgr sync.Once
var _singleSerialMgr *DeviceMgr

func GetDeviceMgr() *DeviceMgr {
	_onceGetDeviceMgr.Do(func() {
		_singleSerialMgr = &DeviceMgr{mapDevice: make(map[string]Device)}
	})
	return _singleSerialMgr
}

type DeviceMgr struct {
	mu        sync.Mutex
	mapDevice map[string]Device
}

// AddDevices 新增
func (o *DeviceMgr) AddDevices(infos []protocol.DevInfo) {
	o.mu.Lock()
	defer o.mu.Unlock()
	for _, v := range infos {
		if _, ok := o.mapDevice[v.DevCode]; ok {
			logrus.Errorf("AddDevices:已添加该设备，不可重复添加:devcode=%s", v.DevCode)
			continue
		}
		di := v
		if device := CreateDevice(v.ProtocolType, &di); device != nil {
			device.Start()
			o.mapDevice[v.DevCode] = device
		}
	}
}

// RemoveDevice 删除
func (o *DeviceMgr) RemoveDevice(devCode string) {
	o.mu.Lock()
	defer o.mu.Unlock()
	if device, ok := o.mapDevice[devCode]; ok {
		device.Stop()
		delete(o.mapDevice, devCode)
	}
}

// UpdateDevices 新增或修改
func (o *DeviceMgr) UpdateDevices(code uint8, infos []protocol.DevInfo) {
	//先遍历devinfos
	deviceInfos := make(map[string]*protocol.DevInfo)
	for _, v := range infos {
		deviceInfos[v.DevCode] = &v
	}

	o.mu.Lock()
	defer o.mu.Unlock()
	if len(infos) == 0 {
		for k, v := range o.mapDevice {
			if v.GetDevInfo().Code == code {
				v.Stop()
				delete(o.mapDevice, k)
			}
		}
		return
	}

	//先删除不再用的设备
	for k, v := range o.mapDevice {
		if v.GetDevInfo().Code != code {
			continue
		}
		if _, ok := deviceInfos[k]; !ok {
			v.Stop()
			delete(o.mapDevice, k)
		}
	}

	//再添加新的设备或更新设备
	for _, v := range infos {
		if device, ok := o.mapDevice[v.DevCode]; ok {
			old := device.GetDevInfo()
			if v.ProtocolType == old.ProtocolType { //设备类型没变
				device.UpdateInfo(v)  //更新设备信息
				if v.TID != old.TID { //更新物模型信息
					device.UpdateModel(v.TID, 3)
				}
				continue
			} else {
				device.Stop()
				delete(o.mapDevice, v.DevCode)
			}
		}
		if device := CreateDevice(v.ProtocolType, &v); device != nil {
			device.Start()
			o.mapDevice[v.DevCode] = device
		}
	}
}

// GetDevice 查询
func (o *DeviceMgr) GetDevice(devcode string) Device {
	o.mu.Lock()
	defer o.mu.Unlock()
	if device, ok := o.mapDevice[devcode]; ok {
		return device
	}
	return nil
}

// StopDevice 停止
func (o *DeviceMgr) StopDevice(devCode string) {
	o.mu.Lock()
	defer o.mu.Unlock()
	if device, ok := o.mapDevice[devCode]; ok {
		device.Stop()
		delete(o.mapDevice, devCode)
	}
}

// StopAllDevice 停止所有
func (o *DeviceMgr) StopAllDevice() {
	o.mu.Lock()
	defer o.mu.Unlock()
	for k, v := range o.mapDevice {
		v.Stop()
		delete(o.mapDevice, k)
	}
}

// UpdateModel 更新模型
func (o *DeviceMgr) UpdateModel(tid uint16, flag int) {
	o.mu.Lock()
	defer o.mu.Unlock()
	for _, v := range o.mapDevice {
		v.UpdateModel(tid, flag)
	}
}
