package player

// SetCharacterFlag sets a character flag
func (p *Player) SetCharacterFlag(flag int) {
	if flag > CF_MAXIMUM_FLAG {
		return
	}

	if flag < 32 {
		p.GetInfoStruct().SetFlags(p.GetInfoStruct().GetFlags() | (1 << uint(flag)))
	} else {
		p.GetInfoStruct().SetFlags2(p.GetInfoStruct().GetFlags2() | (1 << uint(flag-32)))
	}
	p.SetCharSheetChanged(true)
}

// ResetCharacterFlag resets a character flag
func (p *Player) ResetCharacterFlag(flag int) {
	if flag > CF_MAXIMUM_FLAG {
		return
	}

	if flag < 32 {
		p.GetInfoStruct().SetFlags(p.GetInfoStruct().GetFlags() & ^(1 << uint(flag)))
	} else {
		p.GetInfoStruct().SetFlags2(p.GetInfoStruct().GetFlags2() & ^(1 << uint(flag-32)))
	}
	p.SetCharSheetChanged(true)
}

// ToggleCharacterFlag toggles a character flag
func (p *Player) ToggleCharacterFlag(flag int) {
	if flag > CF_MAXIMUM_FLAG {
		return
	}

	if p.GetCharacterFlag(flag) {
		p.ResetCharacterFlag(flag)
	} else {
		p.SetCharacterFlag(flag)
	}
}

// GetCharacterFlag returns whether a character flag is set
func (p *Player) GetCharacterFlag(flag int) bool {
	if flag > CF_MAXIMUM_FLAG {
		return false
	}

	var ret bool
	if flag < 32 {
		ret = (p.GetInfoStruct().GetFlags() & (1 << uint(flag))) != 0
	} else {
		ret = (p.GetInfoStruct().GetFlags2() & (1 << uint(flag-32))) != 0
	}
	return ret
}

// ControlFlagsChanged returns whether control flags have changed
func (p *Player) ControlFlagsChanged() bool {
	return p.controlFlags.ControlFlagsChanged()
}

// SetPlayerControlFlag sets a player control flag
func (p *Player) SetPlayerControlFlag(param, paramValue int8, isActive bool) {
	p.controlFlags.SetPlayerControlFlag(param, paramValue, isActive)
}

// SendControlFlagUpdates sends control flag updates to the client
func (p *Player) SendControlFlagUpdates(client *Client) {
	p.controlFlags.SendControlFlagUpdates(client)
}

// NewPlayerControlFlags creates a new PlayerControlFlags instance
func NewPlayerControlFlags() PlayerControlFlags {
	return PlayerControlFlags{
		flagsChanged: false,
		flagChanges:  make(map[int8]map[int8]int8),
		currentFlags: make(map[int8]map[int8]bool),
	}
}

// SetPlayerControlFlag sets a control flag
func (pcf *PlayerControlFlags) SetPlayerControlFlag(param, paramValue int8, isActive bool) {
	pcf.controlMutex.Lock()
	defer pcf.controlMutex.Unlock()

	if pcf.currentFlags[param] == nil {
		pcf.currentFlags[param] = make(map[int8]bool)
	}

	if pcf.currentFlags[param][paramValue] != isActive {
		pcf.currentFlags[param][paramValue] = isActive

		pcf.changesMutex.Lock()
		if pcf.flagChanges[param] == nil {
			pcf.flagChanges[param] = make(map[int8]int8)
		}
		if isActive {
			pcf.flagChanges[param][paramValue] = 1
		} else {
			pcf.flagChanges[param][paramValue] = 0
		}
		pcf.flagsChanged = true
		pcf.changesMutex.Unlock()
	}
}

// ControlFlagsChanged returns whether flags have changed
func (pcf *PlayerControlFlags) ControlFlagsChanged() bool {
	pcf.changesMutex.Lock()
	defer pcf.changesMutex.Unlock()
	return pcf.flagsChanged
}

// SendControlFlagUpdates sends flag updates to client
func (pcf *PlayerControlFlags) SendControlFlagUpdates(client *Client) {
	pcf.changesMutex.Lock()
	defer pcf.changesMutex.Unlock()

	if !pcf.flagsChanged {
		return
	}

	// Send control flag updates to client
	for category, flags := range pcf.flagChanges {
		for flagIndex, value := range flags {
			// TODO: When packet system is available, create and send appropriate packets
			// packet := CreateControlFlagPacket(category, flagIndex, value)
			// client.SendPacket(packet)
			
			// For now, just log the change
			_ = category
			_ = flagIndex
			_ = value
		}
	}

	// Clear changes after sending
	pcf.flagChanges = make(map[int8]map[int8]int8)
	pcf.flagsChanged = false
}
