package player

import (
	"math"

	"eq2emu/internal/entity"
)

// NewPlayerInfo creates a new PlayerInfo instance
func NewPlayerInfo(player *Player) *PlayerInfo {
	return &PlayerInfo{
		player:     player,
		infoStruct: player.GetInfoStruct(),
	}
}

// CalculateXPPercentages calculates XP bar percentages for display
func (pi *PlayerInfo) CalculateXPPercentages() {
	xpNeeded := pi.infoStruct.GetXPNeeded()
	if xpNeeded > 0 {
		divPercent := (float64(pi.infoStruct.GetXP()) / float64(xpNeeded)) * 100.0
		percentage := int16(divPercent) * 10
		whole := math.Floor(divPercent)
		fractional := divPercent - whole

		pi.infoStruct.SetXPYellow(percentage)
		pi.infoStruct.SetXPBlue(int16(fractional * 1000))

		// Vitality bars probably need a revisit
		pi.infoStruct.SetXPBlueVitalityBar(0)
		pi.infoStruct.SetXPYellowVitalityBar(0)

		if pi.player.GetXPVitality() > 0 {
			vitalityTotal := pi.player.GetXPVitality()*10 + float32(percentage)
			vitalityTotal -= float32((int(percentage/100) * 100))
			if vitalityTotal < 100 { // 10%
				pi.infoStruct.SetXPBlueVitalityBar(pi.infoStruct.GetXPBlue() + int16(pi.player.GetXPVitality()*10))
			} else {
				pi.infoStruct.SetXPYellowVitalityBar(pi.infoStruct.GetXPYellow() + int16(pi.player.GetXPVitality()*10))
			}
		}
	}
}

// CalculateTSXPPercentages calculates tradeskill XP bar percentages
func (pi *PlayerInfo) CalculateTSXPPercentages() {
	tsXPNeeded := pi.infoStruct.GetTSXPNeeded()
	if tsXPNeeded > 0 {
		percentage := (float64(pi.infoStruct.GetTSXP()) / float64(tsXPNeeded)) * 1000
		pi.infoStruct.SetTradeskillExpYellow(int16(percentage))
		pi.infoStruct.SetTradeskillExpBlue(int16((percentage - float64(pi.infoStruct.GetTradeskillExpYellow())) * 1000))
	}
}

// SetHouseZone sets the house zone ID
func (pi *PlayerInfo) SetHouseZone(id int32) {
	pi.houseZoneID = id
}

// SetBindZone sets the bind zone ID
func (pi *PlayerInfo) SetBindZone(id int32) {
	pi.bindZoneID = id
}

// SetBindX sets the bind X coordinate
func (pi *PlayerInfo) SetBindX(x float32) {
	pi.bindX = x
}

// SetBindY sets the bind Y coordinate
func (pi *PlayerInfo) SetBindY(y float32) {
	pi.bindY = y
}

// SetBindZ sets the bind Z coordinate
func (pi *PlayerInfo) SetBindZ(z float32) {
	pi.bindZ = z
}

// SetBindHeading sets the bind heading
func (pi *PlayerInfo) SetBindHeading(heading float32) {
	pi.bindHeading = heading
}

// GetHouseZoneID returns the house zone ID
func (pi *PlayerInfo) GetHouseZoneID() int32 {
	return pi.houseZoneID
}

// GetBindZoneID returns the bind zone ID
func (pi *PlayerInfo) GetBindZoneID() int32 {
	return pi.bindZoneID
}

// GetBindZoneX returns the bind X coordinate
func (pi *PlayerInfo) GetBindZoneX() float32 {
	return pi.bindX
}

// GetBindZoneY returns the bind Y coordinate
func (pi *PlayerInfo) GetBindZoneY() float32 {
	return pi.bindY
}

// GetBindZoneZ returns the bind Z coordinate
func (pi *PlayerInfo) GetBindZoneZ() float32 {
	return pi.bindZ
}

// GetBindZoneHeading returns the bind heading
func (pi *PlayerInfo) GetBindZoneHeading() float32 {
	return pi.bindHeading
}

// GetBoatX returns the boat X offset
func (pi *PlayerInfo) GetBoatX() float32 {
	return pi.boatXOffset
}

// GetBoatY returns the boat Y offset
func (pi *PlayerInfo) GetBoatY() float32 {
	return pi.boatYOffset
}

// GetBoatZ returns the boat Z offset
func (pi *PlayerInfo) GetBoatZ() float32 {
	return pi.boatZOffset
}

// GetBoatSpawn returns the boat spawn ID
func (pi *PlayerInfo) GetBoatSpawn() int32 {
	return pi.boatSpawn
}

// SetBoatX sets the boat X offset
func (pi *PlayerInfo) SetBoatX(x float32) {
	pi.boatXOffset = x
}

// SetBoatY sets the boat Y offset
func (pi *PlayerInfo) SetBoatY(y float32) {
	pi.boatYOffset = y
}

// SetBoatZ sets the boat Z offset
func (pi *PlayerInfo) SetBoatZ(z float32) {
	pi.boatZOffset = z
}

// SetBoatSpawn sets the boat spawn
func (pi *PlayerInfo) SetBoatSpawn(spawn *entity.Spawn) {
	if spawn != nil {
		pi.boatSpawn = spawn.GetDatabaseID()
	} else {
		pi.boatSpawn = 0
	}
}

// SetAccountAge sets the account age base
func (pi *PlayerInfo) SetAccountAge(age int32) {
	pi.infoStruct.SetAccountAgeBase(age)
}

// RemoveOldPackets cleans up old packet data
func (pi *PlayerInfo) RemoveOldPackets() {
	pi.changes = nil
	pi.origPacket = nil
	pi.petChanges = nil
	pi.petOrigPacket = nil
}
