// Project Lab - NHTV Igad

#include "UnrealProject.h"
#include "NetworkDoor.h"
#include "NetworkPlayer.h"
#include "NetworkSwitchComponent.h"
#include "CreatureSpawn.h"
#include "DefaultGameMode.h"
#include "NetworkTrigger.h"



ANetworkTrigger::ANetworkTrigger()
{
	openMode = OpenMode::NoKeyRequired;
	cooldown = m_elapsedTime = 0.0f;
	cubeCollider = CreateDefaultSubobject<UBoxComponent>(TEXT("Cube"));
	RootComponent = cubeCollider;

	meshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Static Mesh"));
	meshComponent->AttachTo(RootComponent);

	visualizerComponent = CreateDefaultSubobject<UNetworkSwitchComponent>(TEXT("Visualizer"));
	visualizerComponent->AttachTo(RootComponent);
	cubeCollider->OnComponentBeginOverlap.AddDynamic(this, &ANetworkTrigger::OnOverlapBegin);       // set up a notification for when this component overlaps something
}

void ANetworkTrigger::BeginPlay()
{
	Super::BeginPlay();
	m_elapsedTime = cooldown;
}

void ANetworkTrigger::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (Role != ROLE_Authority)
		return;

	if (cooldown > 0)
 		m_elapsedTime += DeltaTime;
}

void ANetworkTrigger::OnOverlapBegin(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	if (Role != ROLE_Authority)
		return;

	if (!(OtherActor && (OtherActor != this) && OtherComp))
		return;
	if (!OtherActor->IsA(ANetworkPlayer::StaticClass()))
		return;
	if (m_elapsedTime < cooldown)
		return;
	ANetworkPlayer* player = Cast<ANetworkPlayer>(OtherActor);
	AController* const controller = player->GetController();
	if (!controller)
		return;

	if (openMode != OpenMode::NoKeyRequired)
	{
		if (openMode == OpenMode::TreasureRoomKey)
		{
			if (!player->HasKey(PlayerKeyType::TreasureRoomKey))
				return;
			ADefaultGameMode* gameMode = (ADefaultGameMode*)GetWorld()->GetAuthGameMode();
			gameMode->BossHasBeenKilled(player->GetTeam());
		}
		else if (openMode == OpenMode::BossRoomKeyParts)
		{
			// Check if this team has all key fragments
			ANetworkPlayer* const teamMate = player->GetTeamMate();
			int32 playerKeyCompletion = 0, requiredKeyCompletion = 0;
			for (int32 i = keyFragmentMin; i <= keyFragmentMax; i++)
			{
				const int32 lsl = (1 << i);
				requiredKeyCompletion += lsl;
				playerKeyCompletion += player->HasKey(PlayerKeyType(i)) ? lsl : 0;
				if (IsValid(teamMate))
					playerKeyCompletion |= teamMate->HasKey(PlayerKeyType(i)) ? lsl : 0;
			}

			// Key is not complete
			if (requiredKeyCompletion != playerKeyCompletion)
				return;

			// Remove the key fragments
			for (int32 i = keyFragmentMin; i <= keyFragmentMax; i++)
			{
				player->ClearKey(PlayerKeyType(i));
				if (IsValid(teamMate))
					teamMate->ClearKey(PlayerKeyType(i));
			}
		}
	}

	m_elapsedTime = 0;

	for (size_t i = 0; i < creaturesToSpawn.Num(); i++)
	{
		if (!creaturesToSpawn[i]->spawnContinuous)
			creaturesToSpawn[i]->SpawnMobs();
	}
	for (int32 i = 0; i < doorsToOpen.Num(); i++)
	{
		if (doorsToOpen[i])
		{
			switch (toggleMode)
			{
			case ToggleType::CloseObject:
				doorsToOpen[i]->SetDoorState(true);
				break;
			case ToggleType::OpenObject:
				doorsToOpen[i]->SetDoorState(false);
				break;
			case ToggleType::ToggleObject:
				doorsToOpen[i]->ToggleDoor();
				break;
			}
		}
	}
}