package models

import "errors"

//路灯控制器，数据来自web
//海蓝加入这个的通讯编码、设备编码(SN)
//目前使用控制器的通讯编码来进行控制。（设备编码在控制器的标贴上） 通讯编码是控制器上路安装后，我司远程组网后生成的通讯地址（通讯编码）。
//这个在我司项目交付前，会统一提供每盏灯具的通讯编码、设备编码(SN)和经纬度
type DeviceLampController struct {
	ID           string `gorm:"type:varchar(32);primary_key"` //设备ID，DID   //海蓝通信编码
	Name         string `gorm:"type:varchar(64)"`             //灯控名称
	GID          string `gorm:"type:varchar(32)"`             //网关ID
	Brand        int    `gorm:"type:int"`                     //品牌
	Model        int    `gorm:"type:int"`                     //型号
	CtlType      int    `gorm:"type:int"`                     //单灯控制器类型，nb-iot:1,485:2,zigbee:3，zigbeehl:4
	Concentrator string `gorm:"type:varchar(32)"`             //集中器编号，zigbee灯控专用，其他类型灯控置空
	Netid        int    `gorm:"type:int"`                     //网络号，zigbee灯控专用，其他类型灯控置0
	Channel      int    `gorm:"type:int"`                     //通道号，zigbee灯控专用，其他类型灯控置0
	Number       uint16 `gorm:"type:int"`                     //灯编号, zigbee灯控专用，其他类型灯控置0
	OrgNumber    string `gorm:"type:varchar(32)"`             //灯编号, zigbee灯控专用，设备上原始的编号，字符串类型
	Strategy     string `gorm:"type:varchar(32)"`             //关联的策略编码，无则置空，多个则用逗号分开，暂时只支持一个
	Tenant       string `gorm:"type:varchar(8)"`              //租户ID
	State        int    `gorm:"type:int"`                     //1启用，0禁用
	TID          int    `gorm:"type:int"`                     //物模型ID
	//LcModel
}

func (DeviceLampController) TableName() string {
	//从视图查
	return "t_device_lampcontroller"
}

func (o DeviceLampController) Delete() error {
	return G_db.Model(&o).Updates(map[string]interface{}{"state": 0}).Error
}

func (o DeviceLampController) IsExistedByCode() (bool, error) {
	var count int = 0
	err := G_db.Model(&o).Where(" id = ? ", o.ID).Count(&count).Error
	return count > 0, err
}

func IsExistedByConcentrator(concentrator string, number uint16) ([]DeviceLampController, error) {
	var result []DeviceLampController
	err := G_db.Model(&DeviceLampController{}).Where("concentrator = ? and  number = ? and state = 1", concentrator, number).Find(&result).Error
	return result, err
}

func UpdateDeviceLampControllerTID(code string, tid int) error {
	return nil
	sql := `UPDATE t_device_lampcontroller SET t_id = ? WHERE id = ?;`
	return G_db.Raw(sql, tid, code).Error
}

//设备创建和更新
func (o DeviceLampController) SaveFromWeb(ctlType int) error {
	//检查要更新的灯控的集控器、编号是否已存在并且当前处于有效状态
	var (
		conflict = false
		update   = false
		has      = false
		err      error
	)
	if ctlType == 3 {
		arrlamp, err := IsExistedByConcentrator(o.Concentrator, o.Number)
		if err != nil {
			return err
		}
		if len(arrlamp) > 0 {
			conflict = true
		}
		if len(arrlamp) == 1 && arrlamp[0].ID == o.ID {
			update = true
			conflict = false
		}
	}
	//冲突给出提示，不做任何更新或创建
	if conflict {
		return errors.New("数据错误，请确保灯控与系统中其他灯控的集控器和编号不重复")
	}

	//根据ID判断是否已存在
	if !update {
		has, err = o.IsExistedByCode()
		if err != nil {
			return err
		}
	}

	if has || update {
		mapCol := make(map[string]interface{})
		mapCol["name"] = o.Name
		mapCol["g_id"] = o.GID
		mapCol["brand"] = o.Brand
		mapCol["model"] = o.Model
		mapCol["ctl_type"] = o.CtlType
		mapCol["concentrator"] = o.Concentrator
		mapCol["netid"] = o.Netid
		mapCol["channel"] = o.Channel
		mapCol["number"] = o.Number
		mapCol["org_number"] = o.OrgNumber
		mapCol["strategy"] = o.Strategy
		mapCol["tenant"] = o.Tenant
		mapCol["state"] = o.State
		return G_db.Model(&o).Updates(mapCol).Error
	}
	return G_db.Create(&o).Error
}

func LampControllerUpdateState(id string, state int) error {
	return G_db.Model(DeviceLampController{}).Where("id = ?", id).Updates(map[string]interface{}{"state": state}).Error
}

//策略更新
func UpdateStrategy(code []string, strategy string) error {
	return G_db.Model(&DeviceLampController{}).Where("id in (?)",
		code).Update(map[string]interface{}{"strategy": strategy}).Error
}

type ZigbeeLamp struct {
	ID     string
	GID    string
	Number int
}

type ZigbeeHlLamp struct {
	ID           string //灯id
	GID          string //网关id
	Concentrator string //集控id
}

//ctl_type = 3 为zigbee
func GetLampControllerByConcentrator(concentrator string) ([]ZigbeeLamp, error) {
	var lamp []ZigbeeLamp
	err := G_db.Model(&DeviceLampController{}).Select([]string{"id", "g_id",
		"number"}).Where("concentrator = ? and ctl_type = 3 and number > 0 ", concentrator).Scan(&lamp).Error
	return lamp, err
}

//ctl_type = 4 为HLzigbee
func GetLampHlControllerByConcentrator(concentrator string) ([]ZigbeeHlLamp, error) {
	var lamp []ZigbeeHlLamp //id,gid
	err := G_db.Model(&DeviceLampController{}).Select([]string{"id", "g_id",
		"concentrator"}).Where("concentrator = ? and ctl_type = 4", concentrator).Scan(&lamp).Error
	return lamp, err
}

type LampControllerData struct {
	ID           string
	GID          string
	CtlType      int    //单灯控制器类型，nb-iot:1,485:2,zigbee:3
	Concentrator string //集中器编号，zigbee灯控专用，其他类型灯控置空
	Number       uint16 //灯编号, zigbee灯控专用，其他类型灯控置0
}

//获取灯控
func GetLampControllerByID(codes []string) ([]LampControllerData, error) {
	var lamp []LampControllerData
	err := G_db.Model(&DeviceLampController{}).Select([]string{"id", "g_id", "ctl_type",
		"concentrator", "number"}).Where("id in ( ? ) ", codes).Scan(&lamp).Error
	return lamp, err
}

type ZigbeeLampStrategy struct {
	ID           string
	GID          string
	Tenant       string
	Concentrator string //集控器
	Number       int
	Strategy     string
	Sunset       int
	TimeInfo     string
	Longitude    float64
	Latitude     float64
}

//根据集控器编码，获取策略设置为日出日落的zigbee灯控
func GetZigbeeLampstrategyByconcentrator(concentrator string) ([]ZigbeeLampStrategy, error) {
	var zls []ZigbeeLampStrategy
	sql := `SELECT a.id,a.g_id,a.tenant,a.concentrator,a.number,a.strategy,b.sunset,b.time_info,b.longitude,b.latitude FROM 
            (SELECT id,g_id,tenant,concentrator,number,strategy FROM t_device_lampcontroller WHERE concentrator = ? AND ctl_type = 3) a,
            (SELECT id,sunset,time_info,longitude,latitude FROM t_lamp_strategy WHERE sunset = 1) b
            WHERE a.strategy = b.id`
	err := G_db.Raw(sql, concentrator).Scan(&zls).Error
	return zls, err
}

//海蓝根据集控器编码，获取策略设置为日出日落的zigbee灯控
func GetHLZigbeeLampstrategyByconcentrator(concentrator string) ([]ZigbeeLampStrategy, error) {
	var zls []ZigbeeLampStrategy
	sql := `SELECT a.id,a.g_id,a.tenant,a.concentrator,a.number,a.strategy,b.sunset,b.time_info,b.longitude,b.latitude FROM 
            (SELECT id,g_id,tenant,concentrator,number,strategy FROM t_device_lampcontroller WHERE concentrator = ? AND (ctl_type = 4 OR number >= 65500 )) a,
            (SELECT id,sunset,time_info,longitude,latitude FROM t_lamp_strategy WHERE sunset = 1) b
            WHERE a.strategy = b.id`
	err := G_db.Raw(sql, concentrator).Scan(&zls).Error
	return zls, err
}

//根据灯控编码列表，获取所有zigbee灯控
func GetZigbeeLampStrategyByIDs(IDs []string) ([]ZigbeeLampStrategy, error) {
	var zls []ZigbeeLampStrategy
	sql := `SELECT a.id,a.g_id,a.tenant,a.concentrator,a.number,a.strategy,b.sunset,b.time_info,b.longitude,b.latitude FROM 
            (SELECT id,g_id,tenant,concentrator,number,strategy FROM t_device_lampcontroller WHERE id IN (?) AND ctl_type = 3 ) a,
            (SELECT id,sunset,time_info,longitude,latitude FROM t_lamp_strategy) b
            WHERE a.strategy = b.id`
	err := G_db.Raw(sql, IDs).Scan(&zls).Error
	return zls, err
}

//海蓝根据灯控编码列表，获取所有hlzigbee灯控
func GetHLZigbeeLampStrategyByIDs(IDs []string) ([]ZigbeeLampStrategy, error) {
	var zls []ZigbeeLampStrategy
	sql := `SELECT a.id,a.g_id,a.tenant,a.concentrator,a.number,a.strategy,b.sunset,b.time_info,b.longitude,b.latitude FROM 
            (SELECT id,g_id,tenant,concentrator,number,strategy FROM t_device_lampcontroller WHERE id IN (?) AND (ctl_type = 4 OR number >= 65500 )) a,
            (SELECT id,sunset,time_info,longitude,latitude FROM t_lamp_strategy) b
            WHERE a.strategy = b.id`
	err := G_db.Raw(sql, IDs).Scan(&zls).Error
	return zls, err
}

type Ym485LampStrategy struct {
	ID        string
	GID       string
	Tenant    string
	Strategy  string
	Sunset    int
	TimeInfo  string
	Longitude float64
	Latitude  float64
}

//获取485灯控
func GetYm485Lampstrategy(IDs []string) ([]Ym485LampStrategy, error) {
	var ls []Ym485LampStrategy
	var err error
	if len(IDs) == 0 { //获取日出日落
		sql := `SELECT a.id,a.g_id,a.tenant,a.strategy,b.sunset,b.time_info,b.longitude,b.latitude FROM 
            (SELECT id,g_id,tenant,strategy FROM t_device_lampcontroller WHERE ctl_type = 2) a,
            (SELECT id,sunset,time_info,longitude,latitude FROM t_lamp_strategy WHERE sunset = 1) b
            WHERE a.strategy = b.id`
		err = G_db.Raw(sql).Scan(&ls).Error
	} else { //获取指定灯控
		sql := `SELECT a.id,a.g_id,a.tenant,a.strategy,b.sunset,b.time_info,b.longitude,b.latitude FROM 
            (SELECT id,g_id,tenant,strategy FROM t_device_lampcontroller WHERE ctl_type = 2 AND id IN (?) ) a,
            (SELECT id,sunset,time_info,longitude,latitude FROM t_lamp_strategy) b
            WHERE a.strategy = b.id`
		err = G_db.Raw(sql, IDs).Scan(&ls).Error
	}
	return ls, err
}
