package sign

import "eq2emu/internal/spawn"

// Player interface for sign interactions
type Player interface {
	GetDistance(target *spawn.Spawn) float32
	SetX(x float32)
	SetY(y float32)
	SetZ(z float32)
	SetHeading(heading float32)
	GetZone() Zone
	GetTarget() *spawn.Spawn
}

// Client interface for sign interactions
type Client interface {
	GetPlayer() Player
	GetCharacterID() int32
	GetDatabase() Database
	GetCurrentZone() Zone
	SetTemporaryTransportID(id int32)
	SimpleMessage(channel int32, message string)
	Message(channel int32, format string, args ...interface{})
	CheckZoneAccess(zoneName string) bool
	TryZoneInstance(zoneID int32, useDefaults bool) bool
	Zone(zoneName string, useDefaults bool) error
	ProcessTeleport(sign *Sign, destinations []TransportDestination, transporterID int32) error
}

// Zone interface for sign interactions
type Zone interface {
	GetTransporters(client Client, transporterID int32) ([]TransportDestination, error)
	ProcessEntityCommand(command *EntityCommand, player Player, target *spawn.Spawn) error
}

// Database interface for sign persistence
type Database interface {
	GetZoneName(zoneID int32) (string, error)
	GetCharacterName(charID int32) (string, error)
	SaveSignMark(charID int32, widgetID int32, charName string, client Client) error
	LoadSigns(zoneID int32) ([]*Sign, error)
	SaveSign(sign *Sign) error
	DeleteSign(signID int32) error
}

// TransportDestination represents a transport destination
type TransportDestination struct {
	ID          int32
	Name        string
	Description string
	ZoneID      int32
	X           float32
	Y           float32
	Z           float32
	Heading     float32
}

// EntityCommand represents a command that can be executed on an entity
type EntityCommand struct {
	ID          int32
	Command     string
	Name        string
	Description string
}

// Logger interface for sign logging
type Logger interface {
	LogInfo(message string, args ...interface{})
	LogError(message string, args ...interface{})
	LogDebug(message string, args ...interface{})
	LogWarning(message string, args ...interface{})
}

// SignSpawn provides sign functionality for spawn entities
type SignSpawn struct {
	*spawn.Spawn
	*Sign
}

// NewSignSpawn creates a new sign spawn wrapper
func NewSignSpawn(baseSpawn *spawn.Spawn) *SignSpawn {
	sign := NewSign()
	sign.Spawn = baseSpawn

	return &SignSpawn{
		Spawn: baseSpawn,
		Sign:  sign,
	}
}

// IsSign returns true since this is a sign
func (ss *SignSpawn) IsSign() bool {
	return true
}

// HandleUse delegates to the sign's HandleUse method
func (ss *SignSpawn) HandleUse(client Client, command string) error {
	return ss.Sign.HandleUse(client, command)
}

// Copy creates a copy of the sign spawn
func (ss *SignSpawn) Copy() *SignSpawn {
	newSign := ss.Sign.Copy()
	newSpawn := ss.Spawn.Copy()

	return &SignSpawn{
		Spawn: newSpawn,
		Sign:  newSign,
	}
}

// SignAware interface for entities that can interact with signs
type SignAware interface {
	GetSign() *Sign
	IsSign() bool
	HandleSignUse(client Client, command string) error
}

// SignAdapter provides sign functionality for any entity
type SignAdapter struct {
	entity Entity
	sign   *Sign
	logger Logger
}

// Entity interface for things that can have sign functionality
type Entity interface {
	GetID() int32
	GetName() string
	GetDatabaseID() int32
}

// NewSignAdapter creates a new sign adapter
func NewSignAdapter(entity Entity, logger Logger) *SignAdapter {
	return &SignAdapter{
		entity: entity,
		sign:   NewSign(),
		logger: logger,
	}
}

// GetSign returns the sign
func (sa *SignAdapter) GetSign() *Sign {
	return sa.sign
}

// IsSign returns true since this has sign functionality
func (sa *SignAdapter) IsSign() bool {
	return true
}

// HandleSignUse handles sign usage
func (sa *SignAdapter) HandleSignUse(client Client, command string) error {
	if sa.logger != nil {
		sa.logger.LogDebug("Entity %d (%s): Handling sign use with command '%s'",
			sa.entity.GetID(), sa.entity.GetName(), command)
	}

	return sa.sign.HandleUse(client, command)
}

// SetSignTitle sets the sign title
func (sa *SignAdapter) SetSignTitle(title string) {
	sa.sign.SetSignTitle(title)

	if sa.logger != nil {
		sa.logger.LogDebug("Entity %d (%s): Set sign title to '%s'",
			sa.entity.GetID(), sa.entity.GetName(), title)
	}
}

// SetSignDescription sets the sign description
func (sa *SignAdapter) SetSignDescription(description string) {
	sa.sign.SetSignDescription(description)

	if sa.logger != nil {
		sa.logger.LogDebug("Entity %d (%s): Set sign description",
			sa.entity.GetID(), sa.entity.GetName())
	}
}

// SetSignType sets the sign type
func (sa *SignAdapter) SetSignType(signType int8) {
	sa.sign.SetSignType(signType)

	if sa.logger != nil {
		sa.logger.LogDebug("Entity %d (%s): Set sign type to %d",
			sa.entity.GetID(), sa.entity.GetName(), signType)
	}
}

// SetZoneTransport configures the sign for zone transport
func (sa *SignAdapter) SetZoneTransport(zoneID int32, x, y, z, heading float32) {
	sa.sign.SetSignType(SignTypeZone)
	sa.sign.SetSignZoneID(zoneID)
	sa.sign.SetSignZoneX(x)
	sa.sign.SetSignZoneY(y)
	sa.sign.SetSignZoneZ(z)
	sa.sign.SetSignZoneHeading(heading)

	if sa.logger != nil {
		sa.logger.LogDebug("Entity %d (%s): Configured zone transport to zone %d at (%.2f, %.2f, %.2f)",
			sa.entity.GetID(), sa.entity.GetName(), zoneID, x, y, z)
	}
}

// SetSignDistance sets the interaction distance
func (sa *SignAdapter) SetSignDistance(distance float32) {
	sa.sign.SetSignDistance(distance)

	if sa.logger != nil {
		sa.logger.LogDebug("Entity %d (%s): Set sign distance to %.2f",
			sa.entity.GetID(), sa.entity.GetName(), distance)
	}
}

// Validate validates the sign configuration
func (sa *SignAdapter) Validate() []string {
	return sa.sign.Validate()
}

// IsValid returns true if the sign is valid
func (sa *SignAdapter) IsValid() bool {
	return sa.sign.IsValid()
}
