package object

import (
	"time"
)

// SpawnInterface defines the interface that spawn-based objects must implement
// This allows objects to integrate with systems expecting spawn entities
type SpawnInterface interface {
	// Basic identification
	GetID() int32
	GetDatabaseID() int32

	// Zone and positioning
	GetZoneName() string
	SetZoneName(string)
	GetX() float32
	GetY() float32
	GetZ() float32
	GetHeading() float32

	// Spawn properties
	GetSpawnType() int8
	SetSpawnType(int8)
	GetSize() int16
	SetSize(int16)

	// State flags
	IsAlive() bool
	SetAlive(bool)
	IsRunning() bool
	SetRunning(bool)

	// Entity properties for spell/trade integration
	GetFactionID() int32
	SetFactionID(int32)
	GetTarget() int32
	SetTarget(int32)
}

// ObjectInterface defines the interface for interactive objects
type ObjectInterface interface {
	SpawnInterface

	// Object-specific properties
	IsObject() bool
	IsClickable() bool
	SetClickable(bool)
	GetDeviceID() int8
	SetDeviceID(int8)

	// Interaction
	HandleUse(clientID int32, command string) error
	ShowsCommandIcon() bool
	SetShowCommandIcon(bool)

	// Merchant functionality
	GetMerchantID() int32
	SetMerchantID(int32)
	GetMerchantType() int8
	SetMerchantType(int8)
	IsCollector() bool
	SetCollector(bool)

	// Transport functionality
	GetTransporterID() int32
	SetTransporterID(int32)

	// Copying
	Copy() ObjectInterface
}

// EntityInterface defines the interface for entities in trade/spell systems
// ObjectSpawn implements this to integrate with existing systems
type EntityInterface interface {
	GetID() int32
	GetName() string
	IsPlayer() bool
	IsBot() bool
	HasCoins(amount int64) bool
	GetClientVersion() int32
}

// ItemInterface defines the interface for items that objects might provide
// This allows objects to act as item sources (merchants, containers, etc.)
type ItemInterface interface {
	GetID() int32
	GetName() string
	GetQuantity() int32
	GetIcon(version int32) int32
	IsNoTrade() bool
	IsHeirloom() bool
	IsAttuned() bool
	GetCreationTime() time.Time
	GetGroupCharacterIDs() []int32
}

// ObjectSpawnAsEntity is an adapter that makes ObjectSpawn implement EntityInterface
// This allows objects to be used in trade and spell systems
type ObjectSpawnAsEntity struct {
	*ObjectSpawn
	name          string
	isPlayer      bool
	isBot         bool
	coinsAmount   int64
	clientVersion int32
}

// NewObjectSpawnAsEntity creates an entity adapter for an object spawn
func NewObjectSpawnAsEntity(objectSpawn *ObjectSpawn) *ObjectSpawnAsEntity {
	return &ObjectSpawnAsEntity{
		ObjectSpawn:   objectSpawn,
		name:          "Object", // Default name, should be loaded from data
		isPlayer:      false,
		isBot:         false,
		coinsAmount:   0,
		clientVersion: 1000,
	}
}

// EntityInterface implementation for ObjectSpawnAsEntity

// GetName returns the object's name
func (osae *ObjectSpawnAsEntity) GetName() string {
	return osae.name
}

// SetName sets the object's name
func (osae *ObjectSpawnAsEntity) SetName(name string) {
	osae.name = name
}

// IsPlayer returns false for objects
func (osae *ObjectSpawnAsEntity) IsPlayer() bool {
	return osae.isPlayer
}

// IsBot returns whether this object behaves like a bot
func (osae *ObjectSpawnAsEntity) IsBot() bool {
	return osae.isBot
}

// SetBot sets whether this object behaves like a bot
func (osae *ObjectSpawnAsEntity) SetBot(isBot bool) {
	osae.isBot = isBot
}

// HasCoins returns whether the object has sufficient coins (for merchant objects)
func (osae *ObjectSpawnAsEntity) HasCoins(amount int64) bool {
	return osae.coinsAmount >= amount
}

// SetCoins sets the object's coin amount (for merchant objects)
func (osae *ObjectSpawnAsEntity) SetCoins(amount int64) {
	osae.coinsAmount = amount
}

// GetClientVersion returns the client version (default for objects)
func (osae *ObjectSpawnAsEntity) GetClientVersion() int32 {
	return osae.clientVersion
}

// SetClientVersion sets the client version
func (osae *ObjectSpawnAsEntity) SetClientVersion(version int32) {
	osae.clientVersion = version
}

// ObjectItem represents an item provided by an object (merchants, containers, etc.)
type ObjectItem struct {
	id                int32
	name              string
	quantity          int32
	iconID            int32
	noTrade           bool
	heirloom          bool
	attuned           bool
	creationTime      time.Time
	groupCharacterIDs []int32
}

// NewObjectItem creates a new object item
func NewObjectItem(id int32, name string, quantity int32) *ObjectItem {
	return &ObjectItem{
		id:                id,
		name:              name,
		quantity:          quantity,
		iconID:            0,
		noTrade:           false,
		heirloom:          false,
		attuned:           false,
		creationTime:      time.Now(),
		groupCharacterIDs: make([]int32, 0),
	}
}

// ItemInterface implementation for ObjectItem

// GetID returns the item ID
func (oi *ObjectItem) GetID() int32 {
	return oi.id
}

// GetName returns the item name
func (oi *ObjectItem) GetName() string {
	return oi.name
}

// GetQuantity returns the item quantity
func (oi *ObjectItem) GetQuantity() int32 {
	return oi.quantity
}

// SetQuantity sets the item quantity
func (oi *ObjectItem) SetQuantity(quantity int32) {
	oi.quantity = quantity
}

// GetIcon returns the item icon ID
func (oi *ObjectItem) GetIcon(version int32) int32 {
	return oi.iconID
}

// SetIcon sets the item icon ID
func (oi *ObjectItem) SetIcon(iconID int32) {
	oi.iconID = iconID
}

// IsNoTrade returns whether the item is no-trade
func (oi *ObjectItem) IsNoTrade() bool {
	return oi.noTrade
}

// SetNoTrade sets whether the item is no-trade
func (oi *ObjectItem) SetNoTrade(noTrade bool) {
	oi.noTrade = noTrade
}

// IsHeirloom returns whether the item is heirloom
func (oi *ObjectItem) IsHeirloom() bool {
	return oi.heirloom
}

// SetHeirloom sets whether the item is heirloom
func (oi *ObjectItem) SetHeirloom(heirloom bool) {
	oi.heirloom = heirloom
}

// IsAttuned returns whether the item is attuned
func (oi *ObjectItem) IsAttuned() bool {
	return oi.attuned
}

// SetAttuned sets whether the item is attuned
func (oi *ObjectItem) SetAttuned(attuned bool) {
	oi.attuned = attuned
}

// GetCreationTime returns when the item was created
func (oi *ObjectItem) GetCreationTime() time.Time {
	return oi.creationTime
}

// SetCreationTime sets when the item was created
func (oi *ObjectItem) SetCreationTime(creationTime time.Time) {
	oi.creationTime = creationTime
}

// GetGroupCharacterIDs returns the group character IDs for heirloom sharing
func (oi *ObjectItem) GetGroupCharacterIDs() []int32 {
	return oi.groupCharacterIDs
}

// SetGroupCharacterIDs sets the group character IDs for heirloom sharing
func (oi *ObjectItem) SetGroupCharacterIDs(characterIDs []int32) {
	oi.groupCharacterIDs = make([]int32, len(characterIDs))
	copy(oi.groupCharacterIDs, characterIDs)
}

// Utility functions for integration

// CreateMerchantObjectSpawn creates an object spawn configured as a merchant
func CreateMerchantObjectSpawn(merchantID int32, merchantType int8) *ObjectSpawn {
	objectSpawn := NewObjectSpawn()
	objectSpawn.SetMerchantID(merchantID)
	objectSpawn.SetMerchantType(merchantType)
	objectSpawn.SetClickable(true)
	objectSpawn.SetShowCommandIcon(true)

	return objectSpawn
}

// CreateTransportObjectSpawn creates an object spawn configured as a transporter
func CreateTransportObjectSpawn(transporterID int32) *ObjectSpawn {
	objectSpawn := NewObjectSpawn()
	objectSpawn.SetTransporterID(transporterID)
	objectSpawn.SetClickable(true)
	objectSpawn.SetShowCommandIcon(true)

	return objectSpawn
}

// CreateDeviceObjectSpawn creates an object spawn configured as an interactive device
func CreateDeviceObjectSpawn(deviceID int8) *ObjectSpawn {
	objectSpawn := NewObjectSpawn()
	objectSpawn.SetDeviceID(deviceID)
	objectSpawn.SetClickable(true)
	objectSpawn.SetShowCommandIcon(true)

	return objectSpawn
}

// CreateCollectorObjectSpawn creates an object spawn configured as a collector
func CreateCollectorObjectSpawn() *ObjectSpawn {
	objectSpawn := NewObjectSpawn()
	objectSpawn.SetCollector(true)
	objectSpawn.SetClickable(true)
	objectSpawn.SetShowCommandIcon(true)

	return objectSpawn
}
