// Project Lab - NHTV Igad

#include "UnrealProject.h"
#include "MiniBossCreature.h"
#include "NetworkPlayer.h"
#include "CreatureSpawn.h"
#include "AbilityInfo.h"
#include "Effect.h"


AMiniBossCreature::AMiniBossCreature()
{
	PrimaryActorTick.bCanEverTick = true;
	m_usesMana = false;

	target = nullptr;
	m_spawn = nullptr;

	m_castTimer = 0;

	keyDropped = PlayerKeyType::None;
}

void AMiniBossCreature::BeginPlay()
{
	Super::BeginPlay();

	if (Role != ROLE_Authority)
		return;

	// Select two random abilities to cast
	if (IsValid(inheritAbilities) && IsValid(inheritAbilities.GetDefaultObject()))
	{
		TArray<class UAbilityInfo*>& bossAbilities = inheritAbilities.GetDefaultObject()->abilities;
		if (bossAbilities.Num() > 1)
		{
			TArray<int32> abilityIndices;
			for (int32 i = 0; i < bossAbilities.Num(); i++)
				abilityIndices.Add(i);

			while (m_bossAbilityPattern.Num() < 2)
			{
				const int32 index = FMath::Rand() % abilityIndices.Num();
				const int32 ability = abilityIndices[index];
				abilityIndices.RemoveAt(index);
				m_bossAbilityPattern.Add(ability);
			}
		}
		else if (bossAbilities.Num() == 1)
			m_bossAbilityPattern.Add(0);
	}
}
void AMiniBossCreature::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);

	if (Role != ROLE_Authority)
		return;

	// Drop a key
	if (m_health <= 0)
	{
		ANetworkPlayer* const killedBy = Cast<ANetworkPlayer>(GetLastPlayerDamage());
		if (IsValid(killedBy) && keyDropped != PlayerKeyType::None && IsValid(m_spawn) && !m_spawn->hasDroppedKey)
		{
			killedBy->AssignKey(keyDropped, m_spawn);
		}
	}
}

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

	if (Role != ROLE_Authority)
		return;

	// 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)
		{
			// Reset
			target = nullptr;
			m_castTimer = 0;
		}
	}

	if (!IsValid(target))
		return;

	// Boss casting logic
	MoveToPoint(target->GetActorLocation());
	m_castTimer += deltaTime;

	if (m_castTimer > 2.5f && IsValid(inheritAbilities) && IsValid(inheritAbilities.GetDefaultObject()))
	{
		TArray<class UAbilityInfo*>& bossAbilities = inheritAbilities.GetDefaultObject()->abilities;
		
		if (bossAbilities.Num() > 0 && m_bossAbilityPattern.Num() > 0)
		{
			// Cast a random ability
			UAbilityInfo* ability = bossAbilities[m_bossAbilityPattern[FMath::Rand() % m_bossAbilityPattern.Num()]];
			if (IsValid(ability)&& ability->AICastRange*ability->AICastRange>FVector::DistSquared(GetActorLocation(),target->GetActorLocation()))
				CastAbility(ability);
		}

		m_castTimer = 0;
	}
}