package udp

import (
	"bytes"
	"compress/zlib"
	"io"
)

// Compression markers used by EQ2EMu protocol
const (
	CompressedMarker   = 0x5A // Marks zlib compressed data
	UncompressedMarker = 0xA5 // Marks uncompressed data
)

// Compress applies zlib compression with EQ2EMu protocol markers
// Returns compressed data only if compression provides space savings
func Compress(data []byte) ([]byte, error) {
	// Empty data gets uncompressed marker
	if len(data) == 0 {
		return []byte{UncompressedMarker}, nil
	}

	var buf bytes.Buffer
	buf.WriteByte(CompressedMarker)

	// Compress data using zlib
	writer := zlib.NewWriter(&buf)
	if _, err := writer.Write(data); err != nil {
		return nil, err
	}
	if err := writer.Close(); err != nil {
		return nil, err
	}

	// Only use compression if it actually saves space
	if buf.Len() >= len(data)+1 {
		result := make([]byte, len(data)+1)
		result[0] = UncompressedMarker
		copy(result[1:], data)
		return result, nil
	}

	return buf.Bytes(), nil
}

// Decompress handles both compressed and uncompressed data based on markers
func Decompress(data []byte) ([]byte, error) {
	if len(data) == 0 {
		return data, nil
	}

	switch data[0] {
	case UncompressedMarker:
		// Data is uncompressed - return without marker
		return data[1:], nil

	case CompressedMarker:
		// Data is zlib compressed
		return decompressZlib(data[1:])

	default:
		// No compression marker - return as-is
		return data, nil
	}
}

// decompressZlib handles zlib decompression
func decompressZlib(data []byte) ([]byte, error) {
	if len(data) == 0 {
		return nil, io.ErrUnexpectedEOF
	}

	reader := bytes.NewReader(data)
	zlibReader, err := zlib.NewReader(reader)
	if err != nil {
		return nil, err
	}
	defer zlibReader.Close()

	var buf bytes.Buffer
	if _, err := io.Copy(&buf, zlibReader); err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

// IsCompressed checks if data has compression marker
func IsCompressed(data []byte) bool {
	return len(data) > 0 && data[0] == CompressedMarker
}

// IsUncompressed checks if data has uncompressed marker
func IsUncompressed(data []byte) bool {
	return len(data) > 0 && data[0] == UncompressedMarker
}

// HasCompressionMarker checks if data has any compression marker
func HasCompressionMarker(data []byte) bool {
	return IsCompressed(data) || IsUncompressed(data)
}
