// Project Lab - NHTV Igad

#include "UnrealProject.h"
#include "CharacterSubMenu.h"
#include "MenuButton.h"
#include "CharacterCarousel.h"
#include "MenuController.h"
#include "DefaultGameInstance.h"
#include "CharacterSettings.h"
#include "SkillTreeWidget.h"
#include "CharacterBase.h"

TSubclassOf<ACharacterCarousel> carouselClass;

UCharacterSubMenu::UCharacterSubMenu(const FObjectInitializer& init)
{
	carouselClass = ConstructorHelpers::FClassFinder<ACharacterCarousel>(L"/Game/Assets/Blueprints/CharacterCarousel/BP_CharacterCarousel").Class;
}

void UCharacterSubMenu::NativeConstruct()
{
	// Get carousel spawn pos
	FTransform carouselSpawnTransform;
	for(TActorIterator<APlayerStart> it(GetWorld()); it; ++it)
	{
		if((*it)->PlayerStartTag == "Carousel")
			carouselSpawnTransform = (*it)->GetTransform();
	}

	m_carousel = GetWorld()->SpawnActor<ACharacterCarousel>(carouselClass, carouselSpawnTransform);

	// Initialize the characters
	for(int32 i = 0; i < m_carousel->GetCharacterNum(); i++)
		m_UpdateCharacter(i);

	Super::NativeConstruct();

	m_nextButton = AddButton("Next");
	m_nextButton->onPressed.AddDynamic(this, &UCharacterSubMenu::m_Next);
	m_prevButton = AddButton("Previous");
	m_prevButton->onPressed.AddDynamic(this, &UCharacterSubMenu::m_Prev);
	m_editButton = AddButton("Edit");
	m_editButton->onPressed.AddDynamic(this, &UCharacterSubMenu::m_Edit);
	m_newButton = AddButton("New");
	m_newButton->onPressed.AddDynamic(this, &UCharacterSubMenu::m_New);
	m_deleteButton = AddButton("Delete");
	m_deleteButton->onPressed.AddDynamic(this, &UCharacterSubMenu::m_Delete);
	m_backButton = AddButton("Back");
	m_backButton->onPressed.AddDynamic(this, &UCharacterSubMenu::m_Back);
	SetBackButton(m_backButton);
}

void UCharacterSubMenu::NativeDestruct()
{
	Super::NativeDestruct();
	m_carousel->Destroy();
}

void UCharacterSubMenu::UpdateCurrentCharacter()
{
	if(m_carousel)
	{
		m_UpdateCharacter(m_carousel->selectedCharacterIndex);
	}
}

FCharacterClassProperty UCharacterClassPropertySet::GetCharacterClass(int32 classID) const
{
	static FCharacterClassProperty dummy;
	if(classes.Num() > 0)
	{
		return classes[FMath::Clamp(classID, 0, classes.Num() - 1)];
	}
	return dummy;
}

FCharacterClassProperty UCharacterSubMenu::GetCharacterClass(int32 classID) const
{
	return characterClassProperties->GetCharacterClass(classID);
}

TArray<class UAbilityInfo*> UCharacterSubMenu::GetClassAbilities() const
{
	TArray<class UAbilityInfo*> res;
	if(characterClassProperties)
	{
		for(auto cls : characterClassProperties->classes)
		{
			res.Add(cls.basicAttack);
		}
	}
	return res;
}

void UCharacterSubMenu::m_Next()
{
	m_carousel->Next();
}
void UCharacterSubMenu::m_Prev()
{
	m_carousel->Previous();
}
void UCharacterSubMenu::m_New()
{
	m_carousel->CreateNewCharacter(FString("New Character ") + FString::FromInt(m_carousel->GetCharacterNum()+1));
	m_UpdateCharacter(m_carousel->GetCharacterNum() - 1);
}
void UCharacterSubMenu::m_Delete()
{
	if(m_carousel->GetCharacterNum() > 0)
		m_carousel->DeleteCharacter(m_carousel->selectedCharacterIndex);
}
void UCharacterSubMenu::m_Edit()
{
	TArray<FString> options; options.Add("OK");
	if(m_carousel->GetCharacterNum() > 0)
	{
		// Make this the active character
		AMenuController* controller = Cast<AMenuController>(GetOwningPlayer());
		UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());

		// Get save game
		FCharacterSave& save = inst->GetCharacterSettings()->characterSaves[m_carousel->selectedCharacterIndex];
		controller->skillTree->BuildFromState(save.skillTreeState);

		OnEditCharacter();
	}
	else
	{
		ShowMessageBox(FOverlayItemClosed(), "Error", "There are no characters", options, "");
	}
}
void UCharacterSubMenu::m_Back()
{
	CloseSubMenu();
}

void UCharacterSubMenu::m_UpdateCharacter(int32 index)
{
	// Make this the active character
	AMenuController* controller = Cast<AMenuController>(GetOwningPlayer());
	UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());

	// Get save game
	FCharacterSave& save = inst->GetCharacterSettings()->characterSaves[index];

	ACharacterBase* character = m_carousel->GetCharacterModel(index);
	if(character)
	{
		character->SetCustomizations(save.characterCustomization);
		character->EquipSkillsFromSkillTreeState(save.skillTreeState);

		// Set class specific equipment
		if(characterClassProperties)
		{
			FCharacterClassProperty properties = characterClassProperties->GetCharacterClass(save.characterClass);
			character->EquipItems(properties.classItems);
		}
	}
	else
	{
		GERROR("Can't update character " + index + ", it does not have a character model.");
	}
}
