package ym485

import (
	"github.com/valyala/bytebufferpool"
)

// QuerySoftVerAck 1E，查询单灯控制器软件版本响应，终端上报
type QuerySoftVerAck struct {
	Dp      DataPack
	Mark    [4]byte
	Model   string //软件型号，ascii码
	Version string //2字节BCD码，版本号
	Date    string //日期，日月年顺序
}

func (o *QuerySoftVerAck) EnCode(Addr string, Mark [4]byte, Model string, Version string, Date string) (*bytebufferpool.ByteBuffer, error) {
	copy(o.Mark[0:], Mark[0:])
	o.Model = Model
	o.Version = Version
	o.Date = Date

	tmpModel := make([]byte, 16)
	if len(Model) <= 16 {
		copy(tmpModel, o.Model)
	} else {
		copy(tmpModel, []byte(o.Model)[0:16])
	}

	dataBuf := make([]byte, 0, 25)
	dataBuf = append(dataBuf, o.Mark[0:]...)
	dataBuf = append(dataBuf, tmpModel[0:]...)
	dataBuf = append(dataBuf, o.Version[0:]...)
	dataBuf = append(dataBuf, o.Date[0:]...)
	return o.Dp.EnCode(Addr, 0x1E, dataBuf)
}

func (o *QuerySoftVerAck) DeCode(data []byte) error {
	if err := o.Dp.DeCode(data); err == nil {
		len0 := len(o.Dp.Data)
		if len0 >= 25 {
			copy(o.Mark[0:], o.Dp.Data[0:4])
			o.Model = string(o.Dp.Data[4:20])
			o.Version = string(bcd2Ascii(o.Dp.Data[20:22]))
			o.Date = string(bcd2Ascii(o.Dp.Data[22:25]))
		}
		return nil
	} else {
		return err
	}
}

type DeviceState struct {
	State           uint8   //当前状态
	Voltage         float64 //电压，2字节bcd码，1位小数从000.0~999.9
	Current         float64 //电压，2字节bcd码，2位小数从00.00~99.99
	ActivePower     uint16  //有功功率，2字节bcd码，无小数
	LeakageCurrent  float64 //漏电流值，2字节bcd码，2位小数
	BrightnessState uint8   //调光状态，1字节BIN码
	ColorState      uint8   //调色温状态，1字节BIN码
	Degree          float64 //当前电度值，4字节bcd码，2位小数
}

// QueryDeviceStateAck 1E，查询单灯控制器软件版本响应，终端上报
type QueryDeviceStateAck struct {
	Dp    DataPack
	Mark  [4]byte
	V     byte          //数据区版本号，03H
	L     uint8         //路数
	State []DeviceState //路n的状态
}

func (o *QueryDeviceStateAck) EnCode(Addr string, Mark [4]byte, State []DeviceState) (*bytebufferpool.ByteBuffer, error) {
	copy(o.Mark[0:], Mark[0:])
	o.V = 0x03
	o.L = uint8(len(State))
	dataBuf := make([]byte, 0, 6+15*len(State))
	dataBuf = append(dataBuf, o.Mark[0:]...)
	dataBuf = append(dataBuf, o.V, o.L)
	for _, v := range State {
		dataBuf = append(dataBuf, v.State)
		buf, err := EncodeFloat64(v.Voltage, 3, 1)
		if err == nil {
			dataBuf = append(dataBuf, buf...)
		}
		buf, err = EncodeFloat64(v.Current, 2, 2)
		if err == nil {
			dataBuf = append(dataBuf, buf...)
		}
		buf, err = EncodeFloat64(float64(v.ActivePower), 4, 0)
		if err == nil {
			dataBuf = append(dataBuf, buf...)
		}
		buf, err = EncodeFloat64(v.LeakageCurrent, 2, 2)
		if err == nil {
			dataBuf = append(dataBuf, buf...)
		}
		dataBuf = append(dataBuf, v.BrightnessState)
		dataBuf = append(dataBuf, v.ColorState)
		buf, err = EncodeFloat64(v.Degree, 6, 2)
		if err == nil {
			dataBuf = append(dataBuf, buf...)
		}
	}
	return o.Dp.EnCode(Addr, 0x1E, dataBuf)
}

// DeCode 解码串口返回的数据
func (o *QueryDeviceStateAck) DeCode(data []byte) error {
	if err := o.Dp.DeCode(data); err == nil { //串口回的数据校验打包
		len0 := len(o.Dp.Data)
		if len0 >= 6 {
			copy(o.Mark[0:], o.Dp.Data[0:4])
			o.V = o.Dp.Data[4]
			o.L = o.Dp.Data[5]
			tmpData := o.Dp.Data[6:]
			for {
				obj, err := ParseState(tmpData) //解析所有路的电压电度等
				if err == nil {
					o.State = append(o.State, *obj)
					tmpData = tmpData[15:]
				} else {
					break
				}
			}
		}
		return nil
	} else {
		return err
	}
}

func ParseState(data []byte) (*DeviceState, error) {
	if len(data) >= 15 {
		var obj DeviceState
		obj.State = data[0]
		f, err := DecodeFloat64(data[1:3], 1)
		if err == nil {
			obj.Voltage = f
		}
		f, err = DecodeFloat64(data[3:5], 2)
		if err == nil {
			obj.Current = f
		}
		f, err = DecodeFloat64(data[5:7], 0)
		if err == nil {
			obj.ActivePower = uint16(f)
		}
		f, err = DecodeFloat64(data[7:9], 2)
		if err == nil {
			obj.LeakageCurrent = f
		}
		obj.BrightnessState = data[9]
		obj.ColorState = data[10]
		f, err = DecodeFloat64(data[11:15], 2)
		if err == nil {
			obj.Degree = f
		}
		return &obj, nil
	}
	return nil, ErrorInvalidLenght
}
