package onlinecommand

import (
	"encoding/binary"
	"primesys_producer/src/protocol"
	"primesys_producer/src/protocol/crc"
	. "primesys_producer/src/types"
	"primesys_producer/src/utils"
)

// command from server
// protocol no 0x80

type LanguageByte byte

// hardcoded server flag
// var serverFlag string = "0000A040"

const (
	UTFLanguageByte   LanguageByte = 0x01
	ASCIILanguageByte LanguageByte = 0x02
)

const (
	CHINESEBYTE LanguageByte = 0x01
	ENGLISHBYTE LanguageByte = 0x02
)

// return packet from terminal (device)
type OnlineCommandServerPacket struct {
	CommandLength uint8
	ServerFlag    []byte
	Content       []byte
	LanguageByte  LanguageByte
}

func EncodeCommandToTerminal(command string, serflag string) (OnlineCommandServerPacket, error) {

	serverflag := utils.DecodeStringToByte(serflag)
	commandContent := []byte(command)
	commandLen := len(serverflag) + len(commandContent)

	return OnlineCommandServerPacket{
		CommandLength: uint8(commandLen),
		ServerFlag:    serverflag,
		Content:       commandContent,
		LanguageByte:  ENGLISHBYTE,
	}, nil
}

func EncodeCommandPacket(onlineCommand OnlineCommandServerPacket) []byte {
	// byte packet creation
	packet := make([]byte, 0, 20)
	packetLen := 8 + onlineCommand.CommandLength
	protocolNo := byte(protocol.ProtoOnlineCommand)

	crcInput := []byte{byte(packetLen), byte(protocolNo), byte(onlineCommand.CommandLength)}
	crcInput = append(crcInput, onlineCommand.ServerFlag...)
	crcInput = append(crcInput, onlineCommand.Content...)
	crcInput = append(crcInput, 0x00, byte(onlineCommand.LanguageByte))
	crcInput = append(crcInput, serialNumberByte()...)
	hi, lo := crc.CRC16X25Bytes(crcInput)

	packet = append(packet, StartShortByte, StartShortByte, byte(packetLen), protocolNo, byte(onlineCommand.CommandLength))
	packet = append(packet, onlineCommand.ServerFlag...)
	packet = append(packet, onlineCommand.Content...)
	packet = append(packet, 0x00, byte(onlineCommand.LanguageByte))
	packet = append(packet, serialNumberByte()...)
	packet = append(packet, hi, lo, StopByte1, StopByte2)
	return packet
}

func serialNumberByte() []byte {
	var sn uint16 = 25
	snBytes := make([]byte, 2)
	binary.BigEndian.PutUint16(snBytes, sn)
	return snBytes
}
