package vod

import (
	"encoding/binary"

	"github.com/sigurn/crc8"
)

func NewVODHelper(lengthInCRC bool,
	crcInLength bool,
	lengthInLength bool) VODHelper {
	return VODHelper{
		table: crc8.MakeTable(crc8.Params{
			Poly:   0x1D,
			Init:   0,
			RefIn:  false,
			RefOut: false,
			XorOut: 0,
			Check:  0,
			Name:   "CEC-8 VOD",
		}),
		lengthInCRC:    lengthInCRC,
		crcInLength:    crcInLength,
		lengthInLength: lengthInLength,
	}
}

type VODHelper struct {
	table          *crc8.Table
	lengthInCRC    bool
	crcInLength    bool
	lengthInLength bool
}

// Given a list of bytes, we calculate our custom CRC-8 on it, then prepend the length and postpend the crc in place of last byte
// So 0x01 0x02 0x00 -> 0x00 0x05 0x01 0x02 0x00 0xCRC-8(0x01 0x02 0x00)
// If you have an existing VOD that you are modifying, this function expects you to have removed the length and the crc
func (v *VODHelper) AddLengthAndCRC(data []byte) []byte {
	// first 2 bytes are length including length bytes
	length := make([]byte, 2)
	lengthPlus := 0
	if v.crcInLength { // No
		lengthPlus += 1
	}
	if v.lengthInLength { // Yes
		lengthPlus += 2
	}
	binary.BigEndian.PutUint16(length, uint16(len(data)+lengthPlus))

	var crc byte
	if v.lengthInCRC { // no
		data = append(length, data...)
		// calculate crc on data only
		crc = v.GenerateCRC(data)
	} else { // yes
		// calculate crc on data only
		crc = v.GenerateCRC(data)
		data = append(length, data...)
	}
	data = append(data, crc)

	return data
}

func (v *VODHelper) GenerateCRC(data []byte) byte {
	crc := crc8.Checksum(data, v.table)
	return crc
}
