#include "UnrealProject.h"
#include "IngameSkillTree.h"
#include "HexMap.h"
#include "BaseSkillObject.h"
#include "DefaultPlayerState.h"

void AIngameSkillTree::BuildFromState(const FSkillTreeState& state)
{
	for(int32 i = 0; i < state.objects.Num(); i++)
	{
		const FSkillTreeStateObject& obj = state.objects[i];
		if(!obj.skillObject)
		{
			GWARNING("Invalid skill object found in skill tree state, please reset your build.");
			continue;
		}

		FIngameSkillTreeSkill igs;
		igs.placedPoints = obj.placedPoints;
		igs.skillObject = obj.skillObject->GetDefaultObject<UBaseSkillObject>();
		igs.selectedEffectIndex = obj.selectedEffect;
		
		// Check valid effect index
		if(igs.selectedEffectIndex < 0 || igs.selectedEffectIndex >= igs.skillObject->abilityEffects.Num())
		{
			GWARNING("Ability effect out of range for ability " + obj.skillObject->GetName());
			continue;
		}

		igs.selectedEffect = igs.skillObject->abilityEffects[igs.selectedEffectIndex];

		igs.abilityType = -1;
		switch (igs.skillObject->skillShapeType)
		{
		case ESkillShapeType::Active:
			igs.abilityType = 0;
			break;
		case ESkillShapeType::Coop:
		case ESkillShapeType::Sustain:
			igs.abilityType = 1;
			break;
		case ESkillShapeType::Passive:
			igs.abilityType = 2;
			break;
		}

		if(igs.abilityType == -1)
		{
			GWARNING("Ability type invalid for ability " + obj.skillObject->GetName());
			continue;
		}

		m_skills.Add(igs);
	}
}

AIngameSkillTree::AIngameSkillTree(const FObjectInitializer& init)
{
}

AIngameSkillTree::~AIngameSkillTree()
{ 
}

void AIngameSkillTree::BeginPlay()
{
}

TArray<FIngameSkillTreeSkill> AIngameSkillTree::GetSkillsForLevel(ADefaultPlayerState* player)
{
	float powerLevel = player->GetLevel() / (float)player->GetMaxLevel();
	return GetSkillsForLevel(powerLevel);
}

TArray<FIngameSkillTreeSkill> AIngameSkillTree::GetSkillsForLevel(float powerLevel)
{
	TArray<FIngameSkillTreeSkill> res;
	for (int32 i = 0; i < m_skills.Num(); i++)
	{
		UpdatePowerForSkill(m_skills[i], powerLevel);
		if (m_skills[i].power > 0.0f)
			res.Add(m_skills[i]);
	}
	return res;
}

void AIngameSkillTree::UpdatePowerForSkill(FIngameSkillTreeSkill& skill, float level)
{
	float offset = (1.0f - level) * 16.0f;

	int32 hexcount = 0;

	for(int32 i = 0; i < skill.placedPoints.Num(); i++)
	{
		float YPos = (skill.placedPoints[i].X & 1) ? 
			(float(skill.placedPoints[i].Y) + 0.5f) : 
			(float(skill.placedPoints[i].Y));
		if(YPos >= offset) hexcount++;
	}

	skill.level = hexcount;
	skill.power = float(hexcount) / float(skill.placedPoints.Num());
}
