package types

import (
	"io"
)

// FixedString represents a fixed-length string field
type FixedString struct {
	Data []byte
	Size int
}

// NewFixedString creates a new fixed string with the specified size
func NewFixedString(size int) *FixedString {
	return &FixedString{
		Data: make([]byte, size),
		Size: size,
	}
}

// SetString sets the string value, truncating or padding as needed
func (f *FixedString) SetString(s string) {
	copy(f.Data, []byte(s))
	// Pad with zeros if string is shorter than fixed size
	for i := len(s); i < f.Size; i++ {
		f.Data[i] = 0
	}
}

// String returns the string value, trimming null bytes
func (f *FixedString) String() string {
	// Find first null byte
	for i, b := range f.Data {
		if b == 0 {
			return string(f.Data[:i])
		}
	}
	return string(f.Data)
}

// Serialize writes the fixed string to a writer
func (f *FixedString) Serialize(w io.Writer) error {
	_, err := w.Write(f.Data)
	return err
}

// SerializeToBytes writes the fixed string to a byte slice
func (f *FixedString) SerializeToBytes(dest []byte, offset *uint32) {
	copy(dest[*offset:], f.Data)
	*offset += uint32(f.Size)
}

// Deserialize reads a fixed string from a reader
func (f *FixedString) Deserialize(r io.Reader) error {
	_, err := io.ReadFull(r, f.Data)
	return err
}

// FixedArray represents a fixed-size array of primitive types
type FixedArray[T any] struct {
	Data []T
	Size int
}

// NewFixedArray creates a new fixed array with the specified size
func NewFixedArray[T any](size int) *FixedArray[T] {
	return &FixedArray[T]{
		Data: make([]T, size),
		Size: size,
	}
}
