// Project Lab - NHTV Igad

#include "UnrealProject.h"

#include "DefaultPlayerState.h"
#include "DefaultGameState.h"
#include "DefaultGameInstance.h"
#include "NetworkPlayer.h"

int32 maxLevel = 16;

ADefaultPlayerState::ADefaultPlayerState()
{
	// Set the default values for the constant formula variables.
	// BaseXP + (VarXP * (Level ^ Exp));
	m_baseExperience = 200;
	m_variableExperience = 20;
	m_exponentExperience = 1.2f;

	// Default values for the player.
	m_level = 1;
	m_experience = 0;
	character = nullptr;

	// Calculate the experience to level up.
	m_experienceToLevel = m_CalculateExperienceToLevel(m_level);

	kills = 0;
	deaths = 0;
}

void ADefaultPlayerState::BeginPlay()
{
	Super::BeginPlay();
}

void ADefaultPlayerState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	DOREPLIFETIME(ADefaultPlayerState, m_level);
	DOREPLIFETIME(ADefaultPlayerState, m_experience);
	DOREPLIFETIME(ADefaultPlayerState, m_experienceToLevel);
	DOREPLIFETIME(ADefaultPlayerState, character);
	DOREPLIFETIME(ADefaultPlayerState, teamMate);
	DOREPLIFETIME(ADefaultPlayerState, kills);
	DOREPLIFETIME(ADefaultPlayerState, deaths);
}

// The player level gets converted to an int32, because this function is BlueprintCallable, 
// which does not allow int8 values.
int32 ADefaultPlayerState::GetLevel() const
{
	return (int32)m_level;
}

int32 ADefaultPlayerState::GetMaxLevel() const
{
	return maxLevel;
}

int32 ADefaultPlayerState::GetExperience() const
{
	return m_experience;
}
int32 ADefaultPlayerState::GetExperienceToLevel() const
{
	return m_experienceToLevel;
}

void ADefaultPlayerState::GainExperience(int32 gainedExperience)
{
	check(gainedExperience >= 0);
	m_experience += gainedExperience;

	if (m_level == maxLevel)
		return;

	// Check if a player has leveled up (multiple times).
	while (m_experience >= m_experienceToLevel)
	{
		// Level up.
		++m_level;
		m_experience -= m_experienceToLevel;
		// Calculate the experience to level up.
		m_experienceToLevel = m_CalculateExperienceToLevel(m_level);
		if (character)
			character->OnLevelUp_Server(m_level);

		if (m_level == maxLevel)
		{
			m_experience = 0;
			break;
		}
	}
}

void ADefaultPlayerState::SetLevel(int32 level)
{
	if (Role == ROLE_Authority)
	{
		GPRINT("Setting level to " + level);
		m_level = FMath::Clamp(level, 1, maxLevel);
		m_experienceToLevel = m_CalculateExperienceToLevel(m_level + 1);
		m_experience = 0;
		if(character)
		{
			character->OnLevelUp_Server(level);
		}
	}
}

// Refer to the google/excel sheet for the exact value this will generate.
// Google sheet:	https://docs.google.com/spreadsheets/d/1iuSg5efQSg0l2iQ5RLv3wF44RX2-i-gF-1QUB896bVE/edit#gid=0
// Excel sheet:		I:/Y2015A-Y3-BountyMaze/Programming/Documentation/Experience required to level Sheet.xlsx
int32 ADefaultPlayerState::m_CalculateExperienceToLevel(int32 level)
{
	// BaseXP + (VarXP * (Level ^ Exp));
	return m_baseExperience + m_variableExperience * (pow(level, m_exponentExperience));
}

