package spells

import (
	"sync"
)

// LevelArray represents spell level requirements for different classes
type LevelArray struct {
	AdventureClass    int8    // Adventure class ID
	TradeskillClass   int8    // Tradeskill class ID
	SpellLevel        int16   // Required level
	ClassicSpellLevel float32 // Classic spell level calculation
}

// SpellDisplayEffect represents a displayed effect in spell descriptions
type SpellDisplayEffect struct {
	Percentage  int8   // Effect percentage
	Subbullet   int8   // Subbullet indicator
	Description string // Effect description text
	NeedsDBSave bool   // Whether this needs database saving
}

// LUAData represents Lua script data for spells
type LUAData struct {
	Type         int8    // Data type (int, float, bool, string)
	IntValue     int32   // Integer value
	BoolValue    bool    // Boolean value
	FloatValue   float32 // Float value
	StringValue  string  // String value
	StringValue2 string  // Second string value
	IntValue2    int32   // Second integer value
	FloatValue2  float32 // Second float value
	StringHelper string  // Helper string for identification
	NeedsDBSave  bool    // Whether this needs database saving
}

// SpellData contains all core spell information
// This is the main spell data structure converted from C++ SpellData
type SpellData struct {
	// Basic identification
	SpellBookType    int32  // Type of spell book this belongs to
	ID               int32  // Unique spell ID
	InheritedSpellID int32  // ID of spell this inherits from
	Name             string // Spell name
	Description      string // Spell description

	// Visual information
	Icon         int16 // Spell icon ID
	IconHeroicOp int16 // Heroic opportunity icon
	IconBackdrop int16 // Icon backdrop
	SpellVisual  int32 // Visual effect ID

	// Classification
	Type             int16 // Spell type
	SpellType        int8  // Additional spell type classification
	ClassSkill       int32 // Required class skill
	MinClassSkillReq int16 // Minimum class skill requirement
	MasterySkill     int32 // Mastery skill required
	TSLocIndex       int8  // Tradeskill location index
	Tier             int8  // Spell tier
	NumLevels        int8  // Number of levels this spell has

	// Resource requirements
	HPReq            int16   // Health points required
	HPUpkeep         int16   // Health points upkeep
	PowerReq         float32 // Power required to cast
	PowerByLevel     bool    // Power requirement scales by level
	PowerUpkeep      int16   // Power upkeep cost
	SavageryReq      int16   // Savagery required
	SavageryUpkeep   int16   // Savagery upkeep
	DissonanceReq    int16   // Dissonance required
	DissonanceUpkeep int16   // Dissonance upkeep
	ReqConcentration int16   // Concentration required

	// Percentage-based requirements
	PowerReqPercent      int8 // Power requirement as percentage of max
	HPReqPercent         int8 // HP requirement as percentage of max
	SavageryReqPercent   int8 // Savagery requirement as percentage
	DissonanceReqPercent int8 // Dissonance requirement as percentage

	// Targeting and range
	TargetType    int8    // Type of target (self, enemy, group, etc.)
	Range         float32 // Casting range
	MinRange      float32 // Minimum casting range
	Radius        float32 // Area of effect radius
	MaxAOETargets int16   // Maximum AoE targets
	FriendlySpell int8    // Whether this is a friendly spell

	// Timing
	CastTime      int16   // Cast time in deciseconds
	OrigCastTime  int16   // Original cast time (before modifications)
	Recovery      float32 // Recovery time
	Recast        float32 // Recast delay
	LinkedTimer   int32   // Linked timer ID
	CallFrequency int32   // How often spell effect is called

	// Duration and resistibility
	Duration1           int32   // Primary duration
	Duration2           int32   // Secondary duration
	Resistibility       float32 // How resistible the spell is
	DurationUntilCancel bool    // Duration lasts until cancelled

	// Combat and effect properties
	HitBonus               float32 // Hit bonus provided
	CanEffectRaid          int8    // Can affect raid members
	AffectOnlyGroupMembers int8    // Only affects group members
	GroupSpell             int8    // Is a group spell
	DetType                int8    // Detrimental type
	Incurable              bool    // Cannot be cured
	ControlEffectType      int8    // Type of control effect

	// Behavioral flags
	CastType            int8  // Cast type (normal, toggle)
	CastingFlags        int32 // Various casting flags
	CastWhileMoving     bool  // Can cast while moving
	PersistThroughDeath bool  // Persists through death
	NotMaintained       bool  // Not a maintained spell
	IsAA                bool  // Is an Alternate Advancement ability
	CanFizzle           bool  // Can fizzle on cast
	Interruptable       bool  // Can be interrupted
	IsActive            bool  // Spell is active/enabled

	// Savage bar (for certain spell types)
	SavageBar     int8 // Savage bar requirement
	SavageBarSlot int8 // Savage bar slot

	// Messages
	SuccessMessage    string // Message on successful cast
	FadeMessage       string // Message when spell fades
	FadeMessageOthers string // Fade message for others
	EffectMessage     string // Effect message

	// Scripting
	LuaScript string // Lua script filename

	// Versioning and classification
	DisplaySpellTier int8        // Displayed tier
	SOESpellCRC      int32       // SOE spell CRC
	SpellNameCRC     int32       // Spell name CRC
	TypeGroupSpellID int32       // Type group spell ID
	GivenBy          string      // Description of how spell was obtained
	GivenByType      GivenByType // Type of how spell was obtained

	// Thread safety
	mutex sync.RWMutex
}

// NewSpellData creates a new SpellData with default values
func NewSpellData() *SpellData {
	return &SpellData{
		SpellBookType:          SpellBookTypeSpell,
		ID:                     0,
		InheritedSpellID:       0,
		Name:                   "",
		Description:            "",
		Icon:                   0,
		IconHeroicOp:           0,
		IconBackdrop:           0,
		SpellVisual:            0,
		Type:                   0,
		SpellType:              0,
		ClassSkill:             0,
		MinClassSkillReq:       0,
		MasterySkill:           0,
		TSLocIndex:             0,
		Tier:                   1,
		NumLevels:              1,
		HPReq:                  0,
		HPUpkeep:               0,
		PowerReq:               0.0,
		PowerByLevel:           false,
		PowerUpkeep:            0,
		SavageryReq:            0,
		SavageryUpkeep:         0,
		DissonanceReq:          0,
		DissonanceUpkeep:       0,
		ReqConcentration:       0,
		PowerReqPercent:        0,
		HPReqPercent:           0,
		SavageryReqPercent:     0,
		DissonanceReqPercent:   0,
		TargetType:             SpellTargetSelf,
		Range:                  0.0,
		MinRange:               0.0,
		Radius:                 0.0,
		MaxAOETargets:          0,
		FriendlySpell:          1,
		CastTime:               0,
		OrigCastTime:           0,
		Recovery:               0.0,
		Recast:                 0.0,
		LinkedTimer:            0,
		CallFrequency:          0,
		Duration1:              0,
		Duration2:              0,
		Resistibility:          0.0,
		DurationUntilCancel:    false,
		HitBonus:               0.0,
		CanEffectRaid:          0,
		AffectOnlyGroupMembers: 0,
		GroupSpell:             0,
		DetType:                0,
		Incurable:              false,
		ControlEffectType:      0,
		CastType:               SpellCastTypeNormal,
		CastingFlags:           0,
		CastWhileMoving:        false,
		PersistThroughDeath:    false,
		NotMaintained:          false,
		IsAA:                   false,
		CanFizzle:              true,
		Interruptable:          true,
		IsActive:               true,
		SavageBar:              0,
		SavageBarSlot:          0,
		SuccessMessage:         "",
		FadeMessage:            "",
		FadeMessageOthers:      "",
		EffectMessage:          "",
		LuaScript:              "",
		DisplaySpellTier:       1,
		SOESpellCRC:            0,
		SpellNameCRC:           0,
		TypeGroupSpellID:       0,
		GivenBy:                "",
		GivenByType:            GivenByUnset,
	}
}

// GetID returns the spell ID (thread-safe)
func (sd *SpellData) GetID() int32 {
	sd.mutex.RLock()
	defer sd.mutex.RUnlock()
	return sd.ID
}

// SetID updates the spell ID (thread-safe)
func (sd *SpellData) SetID(id int32) {
	sd.mutex.Lock()
	defer sd.mutex.Unlock()
	sd.ID = id
}

// GetName returns the spell name (thread-safe)
func (sd *SpellData) GetName() string {
	sd.mutex.RLock()
	defer sd.mutex.RUnlock()
	return sd.Name
}

// SetName updates the spell name (thread-safe)
func (sd *SpellData) SetName(name string) {
	sd.mutex.Lock()
	defer sd.mutex.Unlock()
	sd.Name = name
}

// GetTier returns the spell tier
func (sd *SpellData) GetTier() int8 {
	sd.mutex.RLock()
	defer sd.mutex.RUnlock()
	return sd.Tier
}

// GetDuration returns the primary spell duration
func (sd *SpellData) GetDuration() int32 {
	sd.mutex.RLock()
	defer sd.mutex.RUnlock()
	return sd.Duration1
}

// GetCastTime returns the cast time
func (sd *SpellData) GetCastTime() int16 {
	sd.mutex.RLock()
	defer sd.mutex.RUnlock()
	return sd.CastTime
}

// GetTargetType returns the target type
func (sd *SpellData) GetTargetType() int8 {
	sd.mutex.RLock()
	defer sd.mutex.RUnlock()
	return sd.TargetType
}

// GetRange returns the casting range
func (sd *SpellData) GetRange() float32 {
	sd.mutex.RLock()
	defer sd.mutex.RUnlock()
	return sd.Range
}

// IsHealSpell determines if this is a healing spell
func (sd *SpellData) IsHealSpell() bool {
	// TODO: Implement based on spell effects or type classification
	return false
}

// IsBuffSpell determines if this is a buff spell
func (sd *SpellData) IsBuffSpell() bool {
	// TODO: Implement based on spell effects or duration
	return sd.GetDuration() > 0 && sd.FriendlySpell == 1
}

// IsDamageSpell determines if this is a damage spell
func (sd *SpellData) IsDamageSpell() bool {
	// TODO: Implement based on spell effects
	return false
}

// IsControlSpell determines if this is a control spell
func (sd *SpellData) IsControlSpell() bool {
	sd.mutex.RLock()
	defer sd.mutex.RUnlock()
	return sd.ControlEffectType > 0
}

// IsOffenseSpell determines if this is an offensive spell
func (sd *SpellData) IsOffenseSpell() bool {
	sd.mutex.RLock()
	defer sd.mutex.RUnlock()
	return sd.FriendlySpell == 0
}

// CanCastWhileStunned returns whether spell can be cast while stunned
func (sd *SpellData) CanCastWhileStunned() bool {
	// Check casting flags for stun immunity
	return (sd.CastingFlags & 0x01) != 0
}

// CanCastWhileMezzed returns whether spell can be cast while mezzed
func (sd *SpellData) CanCastWhileMezzed() bool {
	// Check casting flags for mez immunity
	return (sd.CastingFlags & 0x02) != 0
}

// CanCastWhileStifled returns whether spell can be cast while stifled
func (sd *SpellData) CanCastWhileStifled() bool {
	// Check casting flags for stifle immunity
	return (sd.CastingFlags & 0x04) != 0
}

// CanCastWhileFeared returns whether spell can be cast while feared
func (sd *SpellData) CanCastWhileFeared() bool {
	// Check casting flags for fear immunity
	return (sd.CastingFlags & 0x08) != 0
}

// Clone creates a deep copy of the SpellData
func (sd *SpellData) Clone() *SpellData {
	sd.mutex.RLock()
	defer sd.mutex.RUnlock()

	clone := &SpellData{
		SpellBookType:          sd.SpellBookType,
		ID:                     sd.ID,
		InheritedSpellID:       sd.InheritedSpellID,
		Name:                   sd.Name,
		Description:            sd.Description,
		Icon:                   sd.Icon,
		IconHeroicOp:           sd.IconHeroicOp,
		IconBackdrop:           sd.IconBackdrop,
		SpellVisual:            sd.SpellVisual,
		Type:                   sd.Type,
		SpellType:              sd.SpellType,
		ClassSkill:             sd.ClassSkill,
		MinClassSkillReq:       sd.MinClassSkillReq,
		MasterySkill:           sd.MasterySkill,
		TSLocIndex:             sd.TSLocIndex,
		Tier:                   sd.Tier,
		NumLevels:              sd.NumLevels,
		HPReq:                  sd.HPReq,
		HPUpkeep:               sd.HPUpkeep,
		PowerReq:               sd.PowerReq,
		PowerByLevel:           sd.PowerByLevel,
		PowerUpkeep:            sd.PowerUpkeep,
		SavageryReq:            sd.SavageryReq,
		SavageryUpkeep:         sd.SavageryUpkeep,
		DissonanceReq:          sd.DissonanceReq,
		DissonanceUpkeep:       sd.DissonanceUpkeep,
		ReqConcentration:       sd.ReqConcentration,
		PowerReqPercent:        sd.PowerReqPercent,
		HPReqPercent:           sd.HPReqPercent,
		SavageryReqPercent:     sd.SavageryReqPercent,
		DissonanceReqPercent:   sd.DissonanceReqPercent,
		TargetType:             sd.TargetType,
		Range:                  sd.Range,
		MinRange:               sd.MinRange,
		Radius:                 sd.Radius,
		MaxAOETargets:          sd.MaxAOETargets,
		FriendlySpell:          sd.FriendlySpell,
		CastTime:               sd.CastTime,
		OrigCastTime:           sd.OrigCastTime,
		Recovery:               sd.Recovery,
		Recast:                 sd.Recast,
		LinkedTimer:            sd.LinkedTimer,
		CallFrequency:          sd.CallFrequency,
		Duration1:              sd.Duration1,
		Duration2:              sd.Duration2,
		Resistibility:          sd.Resistibility,
		DurationUntilCancel:    sd.DurationUntilCancel,
		HitBonus:               sd.HitBonus,
		CanEffectRaid:          sd.CanEffectRaid,
		AffectOnlyGroupMembers: sd.AffectOnlyGroupMembers,
		GroupSpell:             sd.GroupSpell,
		DetType:                sd.DetType,
		Incurable:              sd.Incurable,
		ControlEffectType:      sd.ControlEffectType,
		CastType:               sd.CastType,
		CastingFlags:           sd.CastingFlags,
		CastWhileMoving:        sd.CastWhileMoving,
		PersistThroughDeath:    sd.PersistThroughDeath,
		NotMaintained:          sd.NotMaintained,
		IsAA:                   sd.IsAA,
		CanFizzle:              sd.CanFizzle,
		Interruptable:          sd.Interruptable,
		IsActive:               sd.IsActive,
		SavageBar:              sd.SavageBar,
		SavageBarSlot:          sd.SavageBarSlot,
		SuccessMessage:         sd.SuccessMessage,
		FadeMessage:            sd.FadeMessage,
		FadeMessageOthers:      sd.FadeMessageOthers,
		EffectMessage:          sd.EffectMessage,
		LuaScript:              sd.LuaScript,
		DisplaySpellTier:       sd.DisplaySpellTier,
		SOESpellCRC:            sd.SOESpellCRC,
		SpellNameCRC:           sd.SpellNameCRC,
		TypeGroupSpellID:       sd.TypeGroupSpellID,
		GivenBy:                sd.GivenBy,
		GivenByType:            sd.GivenByType,
	}

	return clone
}
