package bx

import (
	"encoding/binary"
)

const (
	DefaultCapacity = 128
)

type BxByteArray struct {
	list []byte
	next int
}

func NewBxByteArray(capacity int) *BxByteArray {
	return &BxByteArray{
		list: make([]byte, capacity),
		next: 0,
	}
}

func NewDefaultBxByteArray() *BxByteArray {
	return NewBxByteArray(DefaultCapacity)
}

func (b *BxByteArray) add(data byte) {
	if b.next == len(b.list) {
		b.list = append(b.list, make([]byte, len(b.list)*2)...)
	}
	b.list[b.next] = data
	b.next++
}

func (b *BxByteArray) addInt16(data int16, endian int) {
	if b.next+1 >= len(b.list) {
		b.list = append(b.list, make([]byte, len(b.list)*2)...)
	}

	if endian == 0 { // LITTLE
		binary.LittleEndian.PutUint16(b.list[b.next:], uint16(data))
	} else { // BIG
		binary.BigEndian.PutUint16(b.list[b.next:], uint16(data))
	}

	b.next += 2
}

func (b *BxByteArray) addInt(data int32, endian int) {
	if b.next+3 >= len(b.list) {
		b.list = append(b.list, make([]byte, len(b.list)*2)...)
	}

	if endian == 0 { // LITTLE
		binary.LittleEndian.PutUint32(b.list[b.next:], uint32(data))
	} else { // BIG
		binary.BigEndian.PutUint32(b.list[b.next:], uint32(data))
	}

	b.next += 4
}

func (b *BxByteArray) addBytes(src []byte) {
	if src != nil {
		if b.next+len(src)-1 >= len(b.list) {
			b.list = append(b.list, make([]byte, len(b.list)+len(src))...)
		}

		copy(b.list[b.next:], src)
		b.next += len(src)
	}
}

func (b *BxByteArray) addBytesOffsetLength(src []byte, offset int, length int) {
	if src != nil {
		if b.next+length-1 >= len(b.list) {
			b.list = append(b.list, make([]byte, len(b.list)+length)...)
		}

		copy(b.list[b.next:], src[offset:offset+length])
		b.next += length
	}
}

func (b *BxByteArray) set(index int, data byte) {
	if index < len(b.list) {
		b.list[index] = data
	}
}

func (b *BxByteArray) get(index int) byte {
	return b.list[index]
}

func (b *BxByteArray) Build() []byte {
	return b.list[:b.next]
}

func (b *BxByteArray) size() int {
	return b.next
}

func (b *BxByteArray) clear() {
	b.next = 0
}
