package bx

import (
	"bytes"
	"encoding/binary"
)

type BxAreaDynamic struct {
	BaseArea
	is5K bool
	//
	// id
	// 动态区域编号
	// 注意：该参数只对动态区有效，其他区域为默认
	// 值，动态区必须统一编号，编号从 0 开始递增。
	id byte
	// 行间距
	lineSpace byte
	// 动态区运行模式
	//0—动态区数据循环显示。
	//1—动态区数据显示完成后静止显示最后一页数
	//据。
	//2—动态区数据循环显示，超过设定时间后数据仍
	//未更新时不再显示
	//3—动态区数据循环显示，超过设定时间后数据仍
	//未更新时显示 Logo 信息,Logo 信息即为动态区域
	//的最后一页信息
	//4—动态区数据顺序显示，显示完最后一页后就不
	//再显示
	//5—动态区数据顺序显示，超过设定次数后数据仍
	//未更新时不再显示
	runMode byte
	// 动 态 区 数 据 超 时 时 间 ， 单 位 为 秒 / 次 数 （ 若
	// RunMode=5，则表示更新次数）
	timeout int16
	// 是否使能语音播放
	//0 表示不使能语音
	//1 表示播放下文中 Data 部分内容
	//2 表示播放下文中 SoundData 部分内容
	soundMode   byte
	soundPerson byte
	soundRepeat byte
	soundVolume byte //todo 默认值0x05
	soundSpeed  byte
	SoundData   []byte
	// extend para len
	extendParaLen byte
	// type setting
	// 属于 extend para
	//typeSetting byte
	// text alignment
	alignment byte
	// single line
	singleLine byte
	// 是否自动换行
	// 是否自动换行
	// 0x01——不自动换行，显示数据在换行时必须插入
	// 换行符
	// 0x02——自动换行，显示内容不需要换行符，但是
	// 只能使用统一的中文字体和英文字体
	autoNewLine byte
	// 显示方式
	//0x01——静止显示
	//0x02——快速打出
	//0x03——向左移动
	//0x04——向右移动
	//0x05——向上移动
	//0x06——向下移动
	dispMode byte
	exitMode byte
	speed    byte
	holdTime byte
	data     []byte
}

func NewBxAreaDynamic(id, runMode, dispMode byte, x uint16, y uint16, w uint16, h uint16, data []byte, is5K bool) *BxAreaDynamic {
	return &BxAreaDynamic{
		BaseArea:    NewBxArea(0, x, y, w, h),
		id:          id,
		data:        data,
		is5K:        is5K,
		timeout:     5,
		runMode:     runMode,
		soundVolume: 0x05,
		soundSpeed:  0x05,
		singleLine:  0x02,
		autoNewLine: 0x01,
		dispMode:    dispMode,
		speed:       0x0a,
		holdTime:    0x08,
	}
}

func (b *BxAreaDynamic) Length() int16 {
	return 27 + int16(len(b.data))
}

func (b *BxAreaDynamic) Build() []byte {
	w := bytes.NewBuffer(make([]byte, 0, 1024))
	binary.Write(w, binary.LittleEndian, b.typ)
	x8 := b.GetX()
	w8 := b.GetW()
	if b.is5K {
		x8 = b.x / 8
		w8 = b.w / 8
	}
	binary.Write(w, binary.LittleEndian, x8)
	binary.Write(w, binary.LittleEndian, b.GetY())
	binary.Write(w, binary.LittleEndian, w8)
	binary.Write(w, binary.LittleEndian, b.GetH())
	// 动态区编号
	binary.Write(w, binary.LittleEndian, b.id)
	// 行间距
	binary.Write(w, binary.LittleEndian, b.lineSpace)
	// 运行模式
	binary.Write(w, binary.LittleEndian, b.runMode)
	binary.Write(w, binary.LittleEndian, b.timeout)
	binary.Write(w, binary.LittleEndian, b.soundMode)
	if b.soundMode == 0x01 || b.soundMode == 0x02 {
		pr := ((b.soundRepeat << 4) & 0xf0) | (b.soundPerson & 0x0f)
		binary.Write(w, binary.LittleEndian, pr)
		binary.Write(w, binary.LittleEndian, b.soundVolume)
		binary.Write(w, binary.LittleEndian, b.soundSpeed)
	}
	if b.soundMode == 0x02 {
		soundDataLen := len(b.SoundData)
		binary.Write(w, binary.LittleEndian, int32(soundDataLen))
		binary.Write(w, binary.LittleEndian, b.SoundData)
	}
	// extendParaLen
	binary.Write(w, binary.LittleEndian, b.extendParaLen)
	binary.Write(w, binary.LittleEndian, b.alignment)
	binary.Write(w, binary.LittleEndian, b.singleLine)
	binary.Write(w, binary.LittleEndian, b.autoNewLine)
	binary.Write(w, binary.LittleEndian, b.dispMode)
	binary.Write(w, binary.LittleEndian, b.exitMode)
	binary.Write(w, binary.LittleEndian, b.speed)
	binary.Write(w, binary.LittleEndian, b.holdTime)
	binary.Write(w, binary.LittleEndian, int32(len(b.data)))
	binary.Write(w, binary.LittleEndian, b.data)

	return w.Bytes()
}

func (b *BxAreaDynamic) SetSoundMode(soundMode byte) {
	if soundMode > 2 {
		b.soundMode = 0x02
	} else {
		b.soundMode = soundMode
	}
}

func (b *BxAreaDynamic) SetSoundPerson(soundPerson byte) {
	if soundPerson > 5 {
		b.soundPerson = 0
	} else {
		b.soundPerson = soundPerson
	}
}

func (b *BxAreaDynamic) SetSoundRepeat(soundRepeat byte) {
	if soundRepeat > 15 {
		b.soundRepeat = 15
	} else {
		b.soundRepeat = soundRepeat
	}
}

func (b *BxAreaDynamic) SetSoundVolume(soundVolume byte) {
	if soundVolume > 10 {
		b.soundVolume = 10
	} else {
		b.soundVolume = soundVolume
	}
}

func (b *BxAreaDynamic) SetSoundSpeed(soundSpeed byte) {
	if soundSpeed < 1 {
		b.soundSpeed = 1
	} else if soundSpeed > 10 {
		b.soundSpeed = 10
	} else {
		b.soundSpeed = soundSpeed
	}
}
