package m9z

// 手动控制指令
import (
	"encoding/binary"
	"fmt"
	"github.com/gogf/gf/v2/errors/gerror"

	"strings"
	"tgk-touch/internal/global"
)

type ManualData struct {
	Able        bool   `json:"disable"`      //是否是手动控制状态
	BackupByte1 byte   `json:"backup_byte1"` //备用字节下标1
	Loops       []Loop `json:"loops"`        //回路数据
	BackupByte4 byte   `json:"backup_byte4"` //备用字节下标4
}
type Loop struct {
	Index  int    `json:"index"` // 0 D0 回路0
	Name   string `json:"name"`  // 0 #1 回路
	IsOpen bool   `json:"is_open"`
	Pwm    int    `json:"pwm"` // 功率百分比
}

func BuildManualData(enable, isOpen bool, pwm int) *ManualData {
	md := &ManualData{
		Able: enable,
	}
	loops := make([]Loop, 10)
	for i := range loops {
		loops[i].Index = i
		loops[i].IsOpen = isOpen
		loops[i].Pwm = pwm
	}
	md.Loops = loops
	return md
}
func (md *ManualData) Write(deviceId string) error {
	return ManualWrite(deviceId, md)
}
func (md *ManualData) Display() string {
	// 改用strings.Builder提升拼接性能（避免不可变字符串频繁创建临时对象）
	var sb strings.Builder
	// 遍历循环列表
	for _, l := range md.Loops {
		// 将bool类型的IsOpen转为1（true）或0（false）
		isOpenNum := 0
		if l.IsOpen {
			isOpenNum = 1
		}
		// 拼接格式：索引-开关状态(1/0)-调光值,
		fmt.Fprintf(&sb, "%d-%d-%d,", l.Index, isOpenNum, l.Pwm)
	}
	// 转换为字符串并去除末尾多余的逗号（若字符串非空）
	result := sb.String()
	return fmt.Sprintf("%v-%s", md.Able, strings.TrimSuffix(result, ","))

}
func ManualRead(deviceId string) (*ManualData, error) {

	manualResult := new(ManualData)
	readResp, err := ReadCmd(deviceId, manual, "读取手动控制参数")
	if err != nil {
		return nil, err
	}
	manualResult.Able = readResp.Data[0] == 01
	manualResult.BackupByte1 = readResp.Data[1]
	manualResult.BackupByte4 = readResp.Data[4]
	// 解析10路的继电器动作状态
	relayBits := BytesToUint16LE(readResp.Data[2:4])
	g.Log().Debugf("继电器状态（二进制）: %016b ,% X", relayBits, readResp.Data[2:4]) // 补零显示16位

	loops := make([]Loop, 10)
	for i := 0; i < 10; i++ {
		var loop Loop
		bit := (relayBits >> i) & 0x01 // 取第i位的值
		loop.IsOpen = bit == 1
		loop.Index = i
		loop.Name = fmt.Sprintf("#%+v", i+1)
		loops[i] = loop
	}
	pwms := readResp.Data[5:len(readResp.Data)]
	// 确定要处理的元素数量，取两者中的较小值
	processCount := len(pwms)
	if len(loops) < processCount {
		processCount = len(loops)
	}

	// 只循环到有效的索引范围
	for index := 0; index < processCount; index++ {
		loops[index].Pwm = hexToPercent(pwms[index])
	}
	manualResult.Loops = loops

	return manualResult, err
}
func ManualWrite(deviceId string, manualData *ManualData) error {
	// 1. 准备数据缓冲区（15字节：1+1+2+1+10）
	data := make([]byte, 15)

	// 2. 填充手动控制状态（Byte0）
	if manualData.Able {
		data[0] = 0x01
	} else {
		data[0] = 0x00
	}

	// 3. 填充备用字节1（Byte1）
	data[1] = manualData.BackupByte1

	// 4. 计算继电器控制位（Byte2-3）
	var relayBits uint16
	for i, loop := range manualData.Loops {
		if loop.IsOpen {
			relayBits |= (1 << i) // 设置对应位为1
		}
	}
	binary.LittleEndian.PutUint16(data[2:4], relayBits) // 小端序写入

	// 5. 填充备用字节4（Byte4）
	data[4] = manualData.BackupByte4

	// 6. 填充回路PWM百分比（Byte5-14）
	for i, loop := range manualData.Loops {
		if loop.Pwm < 0 {
			loop.Pwm = 0
		} else if loop.Pwm > 100 {
			loop.Pwm = 100
		}
		data[5+i] = byte(loop.Pwm) // 直接转换百分比
	}
	//EE 01 02 00 0F    01  00  64 64  00  3F 37 3C 3D 37 40 1C 37 40 1C   23 FF
	//EE 01 02 00 0F    01  01  FF 03  00  32 32 32 32 32 32 32 32 32 32   3D FF
	//g.Log().Debugf("manualData: % X", data)
	// 8. 发送命令
	writeResp, err := WriteCmd(deviceId, manual, data, "写入手动模式")
	if err != nil {
		return err
	}
	if !writeResp.Success {
		return gerror.New("设置失败")
	}
	return nil
}

// Enable 使能
func (md *ManualData) Enable(deviceId string) error {
	md.Able = true
	return ManualWrite(deviceId, md)

}

// Disable 禁用
func (md *ManualData) Disable(deviceId string) error {
	md.Able = false
	return ManualWrite(deviceId, md)
}

// StartLoops 启动指定回路（如果index为空则启动所有）
func (md *ManualData) StartLoops(deviceId string, indexes ...int) error {
	if !md.Able {
		err := md.Enable(deviceId)
		if err != nil {
			return err
		}
	}
	// 如果没有指定index，则操作所有回路
	if len(indexes) == 0 {
		for i := range md.Loops {
			md.Loops[i].IsOpen = true
		}
	} else {
		// 否则只操作指定回路
		for _, idx := range indexes {
			if idx >= 0 && idx < len(md.Loops) {
				md.Loops[idx].IsOpen = true
			} else {
				return fmt.Errorf("无效的回路索引: %d", idx)
			}
		}
	}
	return ManualWrite(deviceId, md)
}

// StopLoops 停止指定回路（如果index为空则停止所有）
func (md *ManualData) StopLoops(deviceId string, indexes ...int) error {
	if !md.Able {
		err := md.Enable(deviceId)
		if err != nil {
			return err
		}
	}
	// 如果没有指定index，则操作所有回路
	if len(indexes) == 0 {
		for i := range md.Loops {
			md.Loops[i].IsOpen = false
		}
	} else {
		// 否则只操作指定回路
		for _, idx := range indexes {
			if idx >= 0 && idx < len(md.Loops) {
				md.Loops[idx].IsOpen = false
			} else {
				return fmt.Errorf("无效的回路索引: %d", idx)
			}
		}
	}
	return ManualWrite(deviceId, md)
}

// SetLoopPWM 设置指定回路的功率百分比
// 参数：
//
//	pwm: 功率百分比 (0-100)
//	indexes: 回路索引（可变参数，不传则设置所有回路）
func (md *ManualData) SetLoopPWM(deviceId string, pwm int, indexes ...int) error {
	if !md.Able {
		err := md.Enable(deviceId)
		if err != nil {
			return err
		}
	}
	// 校验PWM值范围
	if pwm < 0 || pwm > 100 {
		return fmt.Errorf("功率百分比必须在0-100之间，当前值: %d", pwm)
	}

	// 如果没有指定index，则操作所有回路
	if len(indexes) == 0 {
		for i := range md.Loops {
			md.Loops[i].Pwm = pwm
		}
	} else {
		// 操作指定回路
		for _, idx := range indexes {
			if idx >= 0 && idx < len(md.Loops) {
				md.Loops[idx].Pwm = pwm
			} else {
				return fmt.Errorf("无效的回路索引: %d (可用范围: 0-%d)",
					idx, len(md.Loops)-1)
			}
		}
	}

	// 自动提交修改到设备
	return ManualWrite(deviceId, md)
}

// GetLoopPWM 获取指定回路的功率百分比
// 参数：index 回路索引（0-based）
// 返回值：(百分比, 错误信息)
func (md *ManualData) GetLoopPWM(index int) (int, error) {
	if index < 0 || index >= len(md.Loops) {
		return 0, fmt.Errorf("回路索引超出范围（可用：0-%d）", len(md.Loops)-1)
	}
	return md.Loops[index].Pwm, nil
}
