package types

import (
	"encoding/binary"
	"io"
	"math"
)

// Float32 provides serialization methods for float32
type Float32 float32

func (f Float32) Serialize(w io.Writer) error {
	return binary.Write(w, binary.LittleEndian, math.Float32bits(float32(f)))
}

func (f Float32) SerializeToBytes(dest []byte, offset *uint32) {
	binary.LittleEndian.PutUint32(dest[*offset:], math.Float32bits(float32(f)))
	*offset += 4
}

func (f Float32) Size() uint32 {
	return 4
}

func (f *Float32) Deserialize(r io.Reader) error {
	var bits uint32
	if err := binary.Read(r, binary.LittleEndian, &bits); err != nil {
		return err
	}
	*f = Float32(math.Float32frombits(bits))
	return nil
}

// Float64 provides serialization methods for float64
type Float64 float64

func (f Float64) Serialize(w io.Writer) error {
	return binary.Write(w, binary.LittleEndian, math.Float64bits(float64(f)))
}

func (f Float64) SerializeToBytes(dest []byte, offset *uint32) {
	binary.LittleEndian.PutUint64(dest[*offset:], math.Float64bits(float64(f)))
	*offset += 8
}

func (f Float64) Size() uint32 {
	return 8
}

func (f *Float64) Deserialize(r io.Reader) error {
	var bits uint64
	if err := binary.Read(r, binary.LittleEndian, &bits); err != nil {
		return err
	}
	*f = Float64(math.Float64frombits(bits))
	return nil
}

// GetTypeSize returns the size in bytes for common EQ2 types
func GetTypeSize(typeName string) uint32 {
	switch typeName {
	case "int8", "uint8", "byte", "char":
		return 1
	case "int16", "uint16":
		return 2
	case "int32", "uint32", "float", "float32", "color":
		return 4
	case "int64", "uint64", "double", "float64":
		return 8
	default:
		return 0
	}
}

// Serializable interface for types that can be serialized
type Serializable interface {
	Serialize(w io.Writer) error
	SerializeToBytes(dest []byte, offset *uint32)
	Size() uint32
	Deserialize(r io.Reader) error
}