package datastructures

import (
	"bytes"
	"errors"
	"fmt"
)

type SignerResponse struct {
	Version   uint8
	Action    Action
	Reserved1 uint8
	Reserved2 uint8
	Content1  string
	Content2  string
	Content3  string
}

func SignerResponseFromData(lengthBytes []byte, blockData []byte, checkSum byte) (*SignerResponse, error) {
	if len(blockData) < 3 {
		return nil, errors.New("begin of structure corrupt")
	}

	offset := 0
	headerLength := Decode24BitLength(blockData[offset : offset+3])
	offset += 3
	headerBytes := blockData[offset : offset+headerLength]
	offset += headerLength

	content := make([]string, 3)
	for offset < len(blockData) {
		dataLength := Decode24BitLength(blockData[offset : offset+3])
		if len(blockData)-3 < dataLength {
			return nil, errors.New("structure cut off")
		}
		offset += 3
		content = append(content, string(blockData[offset:offset+dataLength]))
		offset += dataLength
	}

	calculated := CalculateXorCheckSum([][]byte{lengthBytes, blockData})
	if checkSum != calculated {
		return nil, errors.New(fmt.Sprintf("invalid checksum expected 0x%x got 0x%x", calculated, checkSum))
	}

	return &SignerResponse{
		Version:   headerBytes[0],
		Action:    Action(headerBytes[1]),
		Reserved1: headerBytes[2],
		Reserved2: headerBytes[3],
		Content1:  content[0],
		Content2:  content[1],
		Content3:  content[2],
	}, nil
}

func (r SignerResponse) Serialize() []byte {
	headerBytes := []byte{r.Version, byte(r.Action), r.Reserved1, r.Reserved2}
	content1Bytes := []byte(r.Content1)
	content2Bytes := []byte(r.Content2)
	content3Bytes := []byte(r.Content3)
	blockBytes := bytes.Join([][]byte{
		encode24BitLength(headerBytes), headerBytes,
		encode24BitLength(content1Bytes), content1Bytes,
		encode24BitLength(content2Bytes), content2Bytes,
		encode24BitLength(content3Bytes), content3Bytes,
	}, []byte{})
	return bytes.Join([][]byte{encode24BitLength(blockBytes), blockBytes}, []byte{})
}