// Project Lab - NHTV Igad

#include "UnrealProject.h"
#include "TouhouBoss.h"
#include "CreatureSpawn.h"
#include "AbilityEventGroup.h"
#include "AbilityInfo.h"
#include "Modifier.h"
#include "NativeModifiers.h"
#include "DefaultGameMode.h"
#include "NetworkPlayer.h"

ATouhouBoss::ATouhouBoss()
{
	PrimaryActorTick.bCanEverTick = true;

/*	AudioComp = CreateDefaultSubobject<UAudioComponent>(TEXT("Boss Audio"));
	if (AudioComp)
	{

		AudioComp->bAutoActivate = false; // with this true the sounds play at spawn (game starts)
	}
	*/
	outOfCombatRegen = 25.0f;
	secondPhasePercentage = 0.5f;
	rotationSpeed = 1;
	cooldown = 2.5f;
}

void ATouhouBoss::BeginPlay()
{
	Super::BeginPlay();
	if (Role != ROLE_Authority)
		return;

	m_engaged = false;
}
void ATouhouBoss::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);

	if (Role != ROLE_Authority)
		return;
	m_walkTimer = 0.0f;

	// Drop a key
	if (m_health <= 0)
	{
		ANetworkPlayer* const killedBy = Cast<ANetworkPlayer>(GetLastPlayerDamage());
		if (IsValid(killedBy) && IsValid(m_spawn))
		{
			killedBy->AssignKey(PlayerKeyType::TreasureRoomKey, m_spawn);
			onBossKilled.Broadcast(killedBy->GetTeam());
		}
	}
}

void ATouhouBoss::m_Engaged()
{
	Super::m_Engaged();
	m_engaged = true;
	ModifierManager* mod = GetModifierManager();
	if (mod != nullptr && m_regenModifier != nullptr)
	{
	
		// Stop regenerating health.
		m_regenModifier->ForceDestroy();
		m_regenModifier = nullptr;
		SetShield(false);
		// Plays a sound indicating that the boss was engaged and start playing the boss music.
		//PlayEngageSound();
	}
}

void ATouhouBoss::m_Disengaged()
{
	Super::m_Disengaged();

	ModifierManager* mod = GetModifierManager();
	if (mod != nullptr && m_regenModifier == nullptr)
	{
		m_engaged = false;
		// Start regenerating health.
		m_regenModifier = mod->AddModifier(ARegenModifier::StaticClass(), 0);
		Cast<ARegenModifier>(m_regenModifier)->regenPerTick = outOfCombatRegen;
		// Remove invincibility if it's active.
		if (m_invincibilityModifier)
		{
			m_invincibilityModifier->ForceDestroy();
			m_invincibilityModifier = nullptr;
			SetShield(false);
		}
	}
}

void ATouhouBoss::Tick(float deltaTime)
{
	Super::Tick(deltaTime);

	// Only execute boss code on the server.
	if (Role != ROLE_Authority)
		return;

	// Calculate health as percentage for deciding which phase the boss should be in.
	float healthPerc = (float)m_health / (float)m_maxHealth;

	// If the distance of the target to the spawn is greater than the aggro range of the spawner,
// then lose the target.
	if (IsValid(target))
	{
		float targetDistSqr = FVector::DistSquared(target->GetActorLocation(), m_spawn->SpawnResetPosition());
		float aggroSqr = m_spawn->deaggroRadius * m_spawn->deaggroRadius;
		if (aggroSqr < targetDistSqr)
		{
			target = nullptr;
		}
	}

	//disengage
	if (!IsValid(target) && m_regenModifier == nullptr)
	{
		m_Disengaged();
	}
	//engage
	else if (target && !m_engaged)
	{
		m_Engaged();
	}

	if (m_engaged)
	{
		if (m_invincibilityModifier)
		{
			m_invincibilityModifier->ForceDestroy();
			m_invincibilityModifier = nullptr;
			SetShield(false);
		}
		if (!IsValid(target))
			return;
		WalkPhase(deltaTime);
	}

}

void ATouhouBoss::WalkPhase(float deltaTime)
{
	MoveToPoint(target->GetActorLocation());
	m_walkTimer += deltaTime;

	// After 2.5 seconds, cast a random ability.
	if (m_walkTimer > cooldown && abilities.Num() > 0 && target)
	{
		// Cast a random ability
		UAbilityInfo* ability = abilities[FMath::Rand() % abilities.Num()];
		if(IsValid(ability))
			CastAbility(ability);

		m_walkTimer = 0;
	}
}

void ATouhouBoss::m_SpawnModifiers()
{
	/*ModifierManager* mod = GetModifierManager();
	if (mod != nullptr)
	{
		//m_regenModifier = mod->AddModifier(ARegenModifier::StaticClass(), 0);
	}*/
}

void ATouhouBoss::SetShield_Implementation(bool on)
{
	FWARNING("shield implemtentation not set in ATouHouBoss");
	return;
}