package zone

import (
	"sync"
	"sync/atomic"
	"time"

	"eq2emu/internal/common"
	"eq2emu/internal/spawn"
)

// Instance types define different zone instance behaviors
type InstanceType int16

const (
	InstanceTypeNone InstanceType = iota
	InstanceTypeGroupLockout
	InstanceTypeGroupPersist
	InstanceTypeRaidLockout
	InstanceTypeRaidPersist
	InstanceTypeSoloLockout
	InstanceTypeSoloPersist
	InstanceTypeTradeskill
	InstanceTypePublic
	InstanceTypePersonalHouse
	InstanceTypeGuildHouse
	InstanceTypeQuest
)

// Core zone server structure - equivalent to C++ ZoneServer class
type ZoneServer struct {
	// Zone identity and configuration
	zoneID          int32
	instanceID      int32
	zoneName        string
	zoneFile        string
	zoneSkyFile     string
	zoneDescription string

	// Zone properties
	cityZone       bool
	alwaysLoaded   bool
	duplicatedZone bool
	duplicatedID   int32
	locked         bool
	isInstance     bool
	instanceType   InstanceType

	// Safe zone coordinates
	safeX       float32
	safeY       float32
	safeZ       float32
	safeHeading float32
	underworld  float32

	// Zone modifiers and rules
	xpModifier     float32
	minimumStatus  int16
	minimumLevel   int16
	maximumLevel   int16
	minimumVersion int16
	expansionFlag  int32
	holidayFlag    int32
	canBind        bool
	canGate        bool
	canEvac        bool

	// Zone times and lockouts
	defaultLockoutTime int32
	defaultReenterTime int32
	defaultResetTime   int32
	groupZoneOption    int8

	// Player and client management
	clients             []Client
	numPlayers          int32
	incomingClients     int32
	lifetimeClientCount int32

	// Weather system
	weatherEnabled         bool
	weatherAllowed         bool
	weatherType            int8
	weatherFrequency       int32
	weatherMinSeverity     float32
	weatherMaxSeverity     float32
	weatherChangeAmount    float32
	weatherDynamicOffset   float32
	weatherChangeChance    int8
	weatherCurrentSeverity float32
	weatherPattern         int8
	weatherLastChangedTime int32
	weatherSignaled        bool
	rain                   float32

	// Time system
	isDusk     bool
	duskHour   int
	duskMinute int
	dawnHour   int
	dawnMinute int

	// Zone message
	zoneMOTD string

	// Thread and processing state
	spawnThreadActive   bool
	combatThreadActive  bool
	initialSpawnThreads int8
	clientThreadActive  bool
	loadingData         bool
	zoneShuttingDown    atomic.Bool
	isInitialized       atomic.Bool
	finishedDepop       bool
	depopZone           bool
	repopZone           bool
	respawnsAllowed     bool

	// Spawn management
	spawnList          map[int32]*spawn.Spawn
	spawnLocationList  map[int32]*SpawnLocation
	changedSpawns      map[int32]bool
	damagedSpawns      []int32
	pendingSpawnList   []*spawn.Spawn
	pendingSpawnRemove map[int32]bool
	spawnDeleteList    map[*spawn.Spawn]int32
	spawnExpireTimers  map[int32]int32

	// Grid system for spatial optimization
	gridMaps map[int32]*GridMap

	// Movement and pathfinding
	pathfinder  IPathfinder
	movementMgr *MobMovementManager

	// System components
	spellProcess  SpellProcess
	tradeskillMgr TradeskillManager

	// Timers
	aggroTimer        *common.Timer
	charsheetChanges  *common.Timer
	clientSave        *common.Timer
	locationProxTimer *common.Timer
	movementTimer     *common.Timer
	regenTimer        *common.Timer
	respawnTimer      *common.Timer
	shutdownTimer     *common.Timer
	spawnRangeTimer   *common.Timer
	spawnUpdateTimer  *common.Timer
	syncGameTimer     *common.Timer
	trackingTimer     *common.Timer
	weatherTimer      *common.Timer
	widgetTimer       *common.Timer

	// Proximity systems
	playerProximities   map[int32]*PlayerProximity
	locationProximities []*LocationProximity
	locationGrids       []*LocationGrid

	// Faction management
	enemyFactionList        map[int32][]int32
	npcFactionList          map[int32][]int32
	reverseEnemyFactionList map[int32][]int32

	// Revive points
	revivePoints []*RevivePoint

	// Transport system
	transportSpawns      []int32
	transportLocations   []*LocationTransportDestination
	transporters         map[int32][]*TransportDestination
	locationTransporters map[int32][]*LocationTransportDestination
	transportMaps        map[int32]string

	// Flight paths
	flightPaths      map[int32]*FlightPathInfo
	flightPathRoutes map[int32][]*FlightPathLocation

	// Loot system
	lootTables     map[int32]*LootTable
	lootDrops      map[int32][]*LootDrop
	spawnLootList  map[int32][]int32
	levelLootList  []*GlobalLoot
	racialLootList map[int16][]*GlobalLoot
	zoneLootList   map[int32][]*GlobalLoot

	// Spawn data caches
	npcList         map[int32]*NPC
	objectList      map[int32]*Object
	signList        map[int32]*Sign
	widgetList      map[int32]*Widget
	groundSpawnList map[int32]*GroundSpawn

	// Entity commands
	entityCommandList map[int32][]*EntityCommand

	// Spawn groups and locations
	spawnGroupAssociations map[int32][]int32
	spawnGroupChances      map[int32]float32
	spawnGroupLocations    map[int32]map[int32]int32
	spawnGroupMap          map[int32][]int32
	spawnLocationGroups    map[int32][]int32

	// Script timers
	spawnScriptTimers []*SpawnScriptTimer

	// Widget management
	widgetTimers   map[int32]int32
	ignoredWidgets map[int32]bool

	// House items
	subspawnList    map[SubspawnType]map[int32]*spawn.Spawn
	housingSpawnMap map[int32]int32

	// Respawn management
	respawnTimers map[int32]int32

	// Zone map
	defaultZoneMap Map

	// Group/raid level tracking
	groupRaidMinLevel   int32
	groupRaidMaxLevel   int32
	groupRaidAvgLevel   int32
	groupRaidFirstLevel int32

	// Watchdog
	watchdogTimestamp int32

	// Lua command queues
	luaQueuedStateCommands map[int32]int32
	luaSpawnUpdateCommands map[int32]map[string]float32

	// Mutexes for thread safety
	masterZoneLock         sync.RWMutex
	masterSpawnLock        sync.RWMutex
	spawnListLock          sync.RWMutex
	clientListLock         sync.RWMutex
	changedSpawnsLock      sync.RWMutex
	gridMapsLock           sync.RWMutex
	spawnLocationListLock  sync.RWMutex
	spawnDeleteListLock    sync.RWMutex
	widgetTimersLock       sync.RWMutex
	ignoredWidgetsLock     sync.RWMutex
	pendingSpawnRemoveLock sync.RWMutex
	luaQueueStateCmdLock   sync.Mutex
	transportLock          sync.RWMutex
	factionLock            sync.RWMutex
	spawnScriptTimersLock  sync.RWMutex
	deadSpawnsLock         sync.RWMutex
	incomingClientsLock    sync.RWMutex
}

// PlayerProximity manages spawn proximity events for Lua scripting
type PlayerProximity struct {
	Distance                float32
	InRangeLuaFunction      string
	LeavingRangeLuaFunction string
	ClientsInProximity      map[Client]bool
	mutex                   sync.RWMutex
}

// LocationProximity handles location-based proximity triggers
type LocationProximity struct {
	X                       float32
	Y                       float32
	Z                       float32
	MaxVariation            float32
	InRangeLuaFunction      string
	LeavingRangeLuaFunction string
	ClientsInProximity      map[Client]bool
	mutex                   sync.RWMutex
}

// LocationGrid manages discovery grids and player tracking
type LocationGrid struct {
	ID        int32
	GridID    int32
	Name      string
	IncludeY  bool
	Discovery bool
	Locations []*Location
	Players   map[Player]bool
	mutex     sync.RWMutex
}

// GridMap provides spawn organization by grid for efficient querying
type GridMap struct {
	GridID int32
	Spawns map[int32]*spawn.Spawn
	mutex  sync.RWMutex
}

// TrackedSpawn represents distance-based spawn tracking for clients
type TrackedSpawn struct {
	Spawn    *spawn.Spawn
	Distance float32
}

// HouseItem represents player housing item management
type HouseItem struct {
	SpawnID  int32
	ItemID   int32
	UniqueID int64
	Item     *Item
}

// RevivePoint represents death recovery locations
type RevivePoint struct {
	ID             int32
	ZoneID         int32
	LocationName   string
	X              float32
	Y              float32
	Z              float32
	Heading        float32
	AlwaysIncluded bool
}

// SpawnScriptTimer represents Lua script timer management
type SpawnScriptTimer struct {
	Timer        int32
	SpawnID      int32
	PlayerID     int32
	Function     string
	CurrentCount int32
	MaxCount     int32
}

// FlightPathInfo contains flight path configuration
type FlightPathInfo struct {
	Speed    float32
	Flying   bool
	Dismount bool
}

// FlightPathLocation represents a waypoint in a flight path
type FlightPathLocation struct {
	X float32
	Y float32
	Z float32
}

// ZoneInfoSlideStructInfo represents zone intro slide information
type ZoneInfoSlideStructInfo struct {
	Unknown1  [2]float32
	Unknown2  [2]int32
	Unknown3  int32
	Unknown4  int32
	Slide     string
	Voiceover string
	Key1      int32
	Key2      int32
}

// ZoneInfoSlideStructTransitionInfo represents slide transition data
type ZoneInfoSlideStructTransitionInfo struct {
	TransitionX    int32
	TransitionY    int32
	TransitionZoom float32
	TransitionTime float32
}

// ZoneInfoSlideStruct combines slide info and transitions
type ZoneInfoSlideStruct struct {
	Info                *ZoneInfoSlideStructInfo
	SlideTransitionInfo []*ZoneInfoSlideStructTransitionInfo
}

// SubspawnType enumeration for different spawn subtypes
type SubspawnType int

const (
	SubspawnTypeCollector SubspawnType = iota
	SubspawnTypeHouseItem
	SubspawnTypeMax = 20
)

// Expansion flags for client compatibility
const (
	ExpansionUnknown  = 1
	ExpansionUnknown2 = 64
	ExpansionUnknown3 = 128
	ExpansionUnknown4 = 256
	ExpansionUnknown5 = 512
	ExpansionDOF      = 1024
	ExpansionKOS      = 2048
	ExpansionEOF      = 4096
	ExpansionROK      = 8192
	ExpansionTSO      = 16384
	ExpansionDOV      = 65536
)

// Spawn script event types
const (
	SpawnScriptSpawn = iota
	SpawnScriptRespawn
	SpawnScriptAttacked
	SpawnScriptTargeted
	SpawnScriptHailed
	SpawnScriptDeath
	SpawnScriptKilled
	SpawnScriptAggro
	SpawnScriptHealthChanged
	SpawnScriptRandomChat
	SpawnScriptConversation
	SpawnScriptTimer
	SpawnScriptCustom
	SpawnScriptHailedBusy
	SpawnScriptCastedOn
	SpawnScriptAutoAttackTick
	SpawnScriptCombatReset
	SpawnScriptGroupDead
	SpawnScriptHearSay
	SpawnScriptPrespawn
	SpawnScriptUseDoor
	SpawnScriptBoard
	SpawnScriptDeboard
)

// Spawn conditional flags
const (
	SpawnConditionalNone       = 0
	SpawnConditionalDay        = 1
	SpawnConditionalNight      = 2
	SpawnConditionalNotRaining = 4
	SpawnConditionalRaining    = 8
)

// Distance constants
const (
	SendSpawnDistance      = 250.0  // When spawns appear visually to the client
	HearSpawnDistance      = 30.0   // Max distance a client can be from a spawn to 'hear' it
	MaxChaseDistance       = 80.0   // Maximum chase distance for NPCs
	RemoveSpawnDistance    = 300.0  // Distance at which spawns are removed from client
	MaxRevivePointDistance = 1000.0 // Maximum distance for revive point selection
)

// Tracking system constants
const (
	TrackingStop = iota
	TrackingStart
	TrackingUpdate
	TrackingCloseWindow
)

const (
	TrackingTypeEntities = iota + 1
	TrackingTypeHarvestables
)

const (
	TrackingSpawnTypePC = iota
	TrackingSpawnTypeNPC
)

// Waypoint categories
const (
	WaypointCategoryGroup = iota
	WaypointCategoryQuests
	WaypointCategoryPeople
	WaypointCategoryPlaces
	WaypointCategoryUser
	WaypointCategoryDirections
	WaypointCategoryTracking
	WaypointCategoryHouses
	WaypointCategoryMap
)

// Weather system constants
const (
	WeatherTypeNormal = iota
	WeatherTypeDynamic
	WeatherTypeRandom
	WeatherTypeChaotic
)

const (
	WeatherPatternDecreasing = iota
	WeatherPatternIncreasing
	WeatherPatternRandom
)

// NewZoneServer creates a new zone server instance with the given zone name
func NewZoneServer(zoneName string) *ZoneServer {
	zs := &ZoneServer{
		zoneName:                zoneName,
		respawnsAllowed:         true,
		finishedDepop:           true,
		canBind:                 true,
		canGate:                 true,
		canEvac:                 true,
		clients:                 make([]Client, 0),
		spawnList:               make(map[int32]*spawn.Spawn),
		spawnLocationList:       make(map[int32]*SpawnLocation),
		changedSpawns:           make(map[int32]bool),
		damagedSpawns:           make([]int32, 0),
		pendingSpawnList:        make([]*spawn.Spawn, 0),
		pendingSpawnRemove:      make(map[int32]bool),
		spawnDeleteList:         make(map[*spawn.Spawn]int32),
		spawnExpireTimers:       make(map[int32]int32),
		gridMaps:                make(map[int32]*GridMap),
		playerProximities:       make(map[int32]*PlayerProximity),
		locationProximities:     make([]*LocationProximity, 0),
		locationGrids:           make([]*LocationGrid, 0),
		enemyFactionList:        make(map[int32][]int32),
		npcFactionList:          make(map[int32][]int32),
		reverseEnemyFactionList: make(map[int32][]int32),
		revivePoints:            make([]*RevivePoint, 0),
		transportSpawns:         make([]int32, 0),
		transportLocations:      make([]*LocationTransportDestination, 0),
		transporters:            make(map[int32][]*TransportDestination),
		locationTransporters:    make(map[int32][]*LocationTransportDestination),
		transportMaps:           make(map[int32]string),
		flightPaths:             make(map[int32]*FlightPathInfo),
		flightPathRoutes:        make(map[int32][]*FlightPathLocation),
		lootTables:              make(map[int32]*LootTable),
		lootDrops:               make(map[int32][]*LootDrop),
		spawnLootList:           make(map[int32][]int32),
		levelLootList:           make([]*GlobalLoot, 0),
		racialLootList:          make(map[int16][]*GlobalLoot),
		zoneLootList:            make(map[int32][]*GlobalLoot),
		npcList:                 make(map[int32]*NPC),
		objectList:              make(map[int32]*Object),
		signList:                make(map[int32]*Sign),
		widgetList:              make(map[int32]*Widget),
		groundSpawnList:         make(map[int32]*GroundSpawn),
		entityCommandList:       make(map[int32][]*EntityCommand),
		spawnGroupAssociations:  make(map[int32][]int32),
		spawnGroupChances:       make(map[int32]float32),
		spawnGroupLocations:     make(map[int32]map[int32]int32),
		spawnGroupMap:           make(map[int32][]int32),
		spawnLocationGroups:     make(map[int32][]int32),
		spawnScriptTimers:       make([]*SpawnScriptTimer, 0),
		widgetTimers:            make(map[int32]int32),
		ignoredWidgets:          make(map[int32]bool),
		subspawnList:            make(map[SubspawnType]map[int32]*spawn.Spawn),
		housingSpawnMap:         make(map[int32]int32),
		respawnTimers:           make(map[int32]int32),
		luaQueuedStateCommands:  make(map[int32]int32),
		luaSpawnUpdateCommands:  make(map[int32]map[string]float32),
		watchdogTimestamp:       int32(time.Now().Unix()),
	}

	// Initialize subspawn lists
	for i := SubspawnType(0); i < SubspawnTypeMax; i++ {
		zs.subspawnList[i] = make(map[int32]*spawn.Spawn)
	}

	zs.loadingData = true
	zs.zoneShuttingDown.Store(false)
	zs.isInitialized.Store(false)

	return zs
}

// String returns a string representation of the instance type
func (it InstanceType) String() string {
	switch it {
	case InstanceTypeNone:
		return "None"
	case InstanceTypeGroupLockout:
		return "Group Lockout"
	case InstanceTypeGroupPersist:
		return "Group Persistent"
	case InstanceTypeRaidLockout:
		return "Raid Lockout"
	case InstanceTypeRaidPersist:
		return "Raid Persistent"
	case InstanceTypeSoloLockout:
		return "Solo Lockout"
	case InstanceTypeSoloPersist:
		return "Solo Persistent"
	case InstanceTypeTradeskill:
		return "Tradeskill"
	case InstanceTypePublic:
		return "Public"
	case InstanceTypePersonalHouse:
		return "Personal House"
	case InstanceTypeGuildHouse:
		return "Guild House"
	case InstanceTypeQuest:
		return "Quest"
	default:
		return "Unknown"
	}
}

// IsShuttingDown returns whether the zone is in the process of shutting down
func (zs *ZoneServer) IsShuttingDown() bool {
	return zs.zoneShuttingDown.Load()
}

// IsInitialized returns whether the zone has completed initialization
func (zs *ZoneServer) IsInitialized() bool {
	return zs.isInitialized.Load()
}

// Shutdown initiates the zone shutdown process
func (zs *ZoneServer) Shutdown() {
	zs.zoneShuttingDown.Store(true)
}
