package auxilary

import (
	"fmt"

	"github.com/k0kubun/pp/v3"
)

// 焦面电箱辅助数据 128 字节 (每 16 行原始图像数据为一组)
type AuxFocalBox struct {
	TransferTime        float32 // 执行转移时间 0.5us/bit
	TrainingDone        byte    // 1B成功；0B失败
	WorkMode            byte    // 工作模式 0B正常；1B故障
	IntegralDirection   byte    // 积分方向 1B正向；0B反向
	PGAGain             byte    // PGA增益
	PIntegrationLevel   uint8   // [5]P波积分级数
	B1IntegrationLevel  uint8   // [6.(7~6)]B1积分级数
	B2IntegrationLevel  uint8   // [6.(5~4)]B2积分级数
	B3IntegrationLevel  uint8   // [6.(3~2)]B3积分级数
	B4IntegrationLevel  uint8   // [6.(1~0)]B4积分级数
	SecPluseState       byte    // [7.(7)]秒脉冲状态 0x1 成功；0x0 失败
	DarkFieldBias       uint16  // [7.(5~0)-8] 暗场偏置 1DN/bit，十六进制无符号整型数
	PWinAddr            uint16  // [9-10]全色开窗地址
	B1WinAddr           uint16  // [11-12]B1开窗地址
	B2WinAddr           uint16  // [13-14]B2开窗地址
	B3WinAddr           uint16  // [15-16]B3开窗地址
	B4WinAddr           uint16  // [17-18]B4开窗地址
	CCDWorkMode         byte    // [38]工作模式 00H=TDI推扫;11H=框幅;
	RawDiskAvailableCap uint16  // [39-40]原始磁盘可用存储容量 量纲：2MBytes/bit
	ZipDiskAvailableCap uint16  // [41-42]压缩盘可用存储容量
	CommandCount        uint8   // [53]指令计数器
	LastCommandCode     uint8   // [54]最后指令代码
}

func (ab *AuxFocalBox) Decode(data []byte) error {
	if len(data) < 128 {
		return fmt.Errorf("eletric box aux data length error")
	}
	byte0 := data[0] & 0b00111111
	ab.TransferTime = float32(uint32(byte0)<<16|uint32(data[1])<<8|uint32(data[2])) * 0.5
	ab.TrainingDone = data[3] & 0b10000000
	ab.WorkMode = data[3] & 0b01000000
	ab.IntegralDirection = data[3] & 0b00100000
	ab.PGAGain = data[3] & 0b00011111
	ab.PIntegrationLevel = data[4]
	ab.B1IntegrationLevel = data[5] >> 6 & 0x03
	ab.B2IntegrationLevel = data[5] >> 4 & 0x03
	ab.B3IntegrationLevel = data[5] >> 2 & 0x03
	ab.B4IntegrationLevel = data[5] & 0x03
	ab.SecPluseState = data[6] >> 7 & 0x01
	ab.DarkFieldBias = uint16(data[6]&0x3f)<<8 | uint16(data[7])
	ab.PWinAddr = uint16(data[8])<<8 | uint16(data[9])
	ab.B1WinAddr = uint16(data[10])<<8 | uint16(data[11])
	ab.B2WinAddr = uint16(data[12])<<8 | uint16(data[13])
	ab.B3WinAddr = uint16(data[14])<<8 | uint16(data[15])
	ab.B4WinAddr = uint16(data[16])<<8 | uint16(data[17])
	ab.CCDWorkMode = data[37]
	ab.RawDiskAvailableCap = (uint16(data[38])<<8 | uint16(data[39])) * 2
	ab.ZipDiskAvailableCap = (uint16(data[40])<<8 | uint16(data[41])) * 2
	ab.CommandCount = data[52]
	ab.LastCommandCode = data[53]
	return nil
}

func (ab AuxFocalBox) Print() {
	pp.Println(ab)
}

func (ab AuxFocalBox) String() string {
	return fmt.Sprintf(
		`执行转移时间：%f us\n
		TrainingDone：%x\n
		工作模式：%x\n
		积分方向：%x\n
		PGA增益：%s
		`,
		ab.TransferTime,
		ab.TrainingDone,
		ab.WorkMode,
		ab.IntegralDirection,
		ab.PGAGainValue(),
	)
}

func (ab AuxFocalBox) PGAGainValue() string {
	switch ab.PGAGain {
	case 0b0000:
		return "0.75x"
	case 0b0001:
		return "1.25x"
	case 0b0010:
		return "1.75x"
	case 0b0011:
		return "2.25x"
	case 0b0100:
		return "2.75x"
	case 0b0101:
		return "3.25x"
	case 0b0110:
		return "3.75x"
	case 0b0111:
		return "4.25x"
	case 0b1000:
		return "4.75x"
	case 0b1001:
		return "5.25x"
	case 0b1010:
		return "5.75x"
	case 0b10000:
		return "1x"
	case 0b10001:
		return "1.5x"
	case 0b10010:
		return "2x"
	case 0b10011:
		return "2.5x"
	case 0b10100:
		return "3x"
	case 0b10101:
		return "3.5x"
	case 0b10110:
		return "4x"
	case 0b10111:
		return "4.5x"
	case 0b11000:
		return "5x"
	case 0b11001:
		return "5.5x"
	case 0b11010:
		return "6x"
	default:
		return "unknown"
	}
}
