#include "UnrealProject.h"
#include "PlayerStateBase.h"

#include "GameStateBase.h"
#include "DefaultGameInstance.h"
#include "SessionManager.h"

APlayerStateBase::APlayerStateBase()
{
	bReplicates = true;
	bAlwaysRelevant = true;
}
void APlayerStateBase::BeginPlay()
{
	Super::BeginPlay();
}

void APlayerStateBase::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	DOREPLIFETIME(APlayerStateBase, m_team);
	DOREPLIFETIME(APlayerStateBase, m_readyToStart);
}

bool APlayerStateBase::SetReadyState_Validate(bool state)
{
	return true;
}
void APlayerStateBase::SetReadyState_Implementation(bool state)
{
	m_readyToStart = state;
}
bool  APlayerStateBase::GetReadyState() const
{
	return m_readyToStart;
}

void APlayerStateBase::Transfer(APlayerStateBase* oldState)
{
	m_team = oldState->m_team;
	UpdatePersona();
}

int32 APlayerStateBase::GetTeam() const
{
	return m_team;
}
bool APlayerStateBase::AutoAssignTeam_Validate()
{
	return true;
}
void APlayerStateBase::AutoAssignTeam_Implementation()
{
	if(m_team > 0)
		return; // Already has a team

	AGameStateBase* const state = Cast<AGameStateBase>(GetWorld()->GetGameState());
	check(state);
	RequestTeamEntry(state->GetOptimalAutoJoinTeam());
}
void APlayerStateBase::UpdatePersona()
{
	UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());
	if (inst && UniqueId.IsValid())
	{
		avatar = inst->sessionManager->GetPlayerAvatar(*UniqueId);
		nickname = inst->sessionManager->GetPlayerName(*UniqueId);
	}
}

bool APlayerStateBase::RequestTeamEntry_Validate(uint8 team)
{
	UWorld* const world = GetWorld();
	check(world);
	AGameStateBase* const state = Cast<AGameStateBase>(world->GetGameState());
	check(state);

	return (team > 0 && team <= state->GetMapTeamCount());
}
void APlayerStateBase::RequestTeamEntry_Implementation(uint8 team)
{
	if(team == m_team)
		return;

	if(m_readyToStart && !(m_team == 0))
		return;

	UWorld* const world = GetWorld();
	if(world)
	{
		AGameStateBase* const state = Cast<AGameStateBase>(world->GetGameState());
		if(state)
		{
			TArray<APlayerStateBase*> players = state->GetPlayers();
			int32 teamSize = 0;
			for(int32 i = 0; i < players.Num(); i++)
			{
				if(players[i] == nullptr)
					continue;
				if(players[i]->GetTeam() == team)
					teamSize++;
			}
			if (teamSize < 2)
			{
				m_team = team;
				state->OnPlayerStateChange_Multi();
			}
		}
	}
}