// Project Lab - NHTV Igad

#pragma once

#include "../Menu/SubMenu.h"
#include "SkillTreeState.h"
#include "AbilityInfo.h"
#include "SkillTreeWidget.generated.h"

class USkillTreeObject;
class USkillWidget;
class UCanvasPanel;
class UHexagonTile;
class ADefaultPlayerController;
struct FHexMap;

UENUM(BlueprintType)
enum class ESkillTreeChangeEvent : uint8
{
	Added,
	Removed,
	Cleared,
};

/*
	Yosho's skill tree?
*/
UCLASS()
class UNREALPROJECT_API USkillTreeWidget : public USubMenu
{
	GENERATED_BODY()
private:
	TArray<class USkillWidget*> m_skillWidgets;
	TArray<class UBaseSkillObject*> m_skillClasses;
	USkillWidget* m_selectedSkill;
	UCanvasPanel* m_skillTreeCanvas;
	UBorder* m_inputCapture;
	UBorder* m_focusBorder;
	class USizeBorder* m_sizeBorder;
	class UToolTipWidget* m_toolTipWidget;
	USkillWidget* m_lastFocusedWidget;

	bool m_interactive;
	bool m_shown;

public:
	UPROPERTY(BlueprintReadOnly, Category = "UI")
	bool isValid;

	TMap<FIntPoint, USkillWidget*> tileMap;
	TArray<UHexagonTile*> tiles;
	UPROPERTY( EditAnywhere, Category = "UI" )
	USkillTreeObject* skillTreeAsset;
	UPROPERTY( EditAnywhere, Category = "UI" )
	FIntPoint rootPoint;
	FVector2D lastGridIndex;

	class UToolTipWidget* GetToolTipWidget() const {
		return m_toolTipWidget;
	}

	UFUNCTION(BlueprintCallable, Category = "UI")
	void SetIsInteractive(bool interactive);
	void UpdateVisibility();
	bool IsShow() const { return m_shown; }
	UFUNCTION(BlueprintCallable, Category = "UI")
	bool IsInteractive() const { return m_interactive; }
	class USizeBorder* GetSizeBorder() const { return m_sizeBorder; }

	UPROPERTY(BlueprintReadOnly)
	EAbilityCategory dominantAbilityCategory;

	// Returns the complete state to reconstruct this skilltree later with BuildFromState()
	UFUNCTION(BlueprintCallable, Category = "Skill Tree")
	FSkillTreeState GetState();
	// Returns the array of used skill objects for visual usage
	UFUNCTION(BlueprintCallable, Category = "Skill Tree")
	TArray<class UBaseSkillObject*> GetApearanceState();
	// Removes all skills from this skill tree widget
	UFUNCTION(BlueprintCallable, Category = "UI")
	void Clear();
	// Restores a given skill tree setup from a state struct
	UFUNCTION(BlueprintCallable, Category = "Skill Tree")
	void BuildFromState(const FSkillTreeState& state);

	UFUNCTION(BlueprintCallable, Category = "UI")
	bool IsUsingSkill(class UBaseSkillObject* skillObject) const;
	UFUNCTION(BlueprintCallable, Category = "UI")
	USkillWidget* GetUsedSkill(class UBaseSkillObject* skillObject);

	UFUNCTION(BlueprintCallable, Category = "UI")
	void Save(int32 saveSlot);
	UFUNCTION(BlueprintCallable, Category = "UI")
	void Load(int32 saveSlot);
	UFUNCTION(BlueprintCallable, Category = "UI")
	void RemoveSkill(class UBaseSkillObject* skillObject);

	void StartDragging(USkillWidget* widget);
	UFUNCTION(BlueprintCallable, Category = "UI")
	void StopDragging(USkillWidget* widget);

	FIntPoint GetGridIndex(FVector2D in) const;

	UPROPERTY(BlueprintReadOnly, Category = "UI")
	USkillWidget* draggingWidget;
	UFUNCTION(BlueprintNativeEvent, Category = "UI")
	void UpdateTextInfo();

	FHexMap* placedSkillHexMap;
	ADefaultPlayerController* parent;

	UFUNCTION(BlueprintCallable, Category = "UI")
	bool ValidateSkillTree();

	UCanvasPanel* GetCanvas()
	{
		return m_skillTreeCanvas;
	}
	void AddSkill( USkillWidget* a_skill, const TArray<FIntPoint>& a_points );
	void RemoveSkill( USkillWidget* a_skill, const TArray<FIntPoint>& a_points );
	UFUNCTION(BlueprintCallable, Category = "UI")
	class USkillWidget* NewSkill(USkillWidget* a_skill, bool controller = false);
	UFUNCTION(BlueprintCallable, Category = "UI")
	class USkillWidget* NewSkillFromAsset(UBaseSkillObject* skillAsset, bool controller = false);
	UFUNCTION(BlueprintCallable, Category = "UI")
	void CancelSkill( USkillWidget* a_skill );

	void UpdateLevel( float level );
	UFUNCTION(BlueprintCallable, Category = "UI")
	void UpdateInfo( float skilltreeHeight, float skilltreeOffset );

	UFUNCTION(BlueprintCallable, Category="UI")
	void Show();
	UFUNCTION(BlueprintCallable, Category="UI")
	void Hide();

	UPROPERTY( EditDefaultsOnly, BlueprintReadOnly, Category = UI )
	TSubclassOf<USkillWidget> WidgetTemplate;

	// Callback for when the skill tree state changes
	DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkillTreeChanged, ESkillTreeChangeEvent, event, UBaseSkillObject*, object);
	UPROPERTY(BlueprintAssignable)
	FOnSkillTreeChanged onSkillTreeChanged;

	virtual void NativeOnSkillTreeChanged(ESkillTreeChangeEvent event, UBaseSkillObject* relevantObject);

	USkillTreeWidget( const FObjectInitializer& init );

	virtual void NativeConstruct() override;
	virtual void NativeDestruct() override;
	virtual void NativeTick(const FGeometry& MyGeometry, float DeltaTime) override;
	virtual FReply NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
	virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
	virtual FReply NativeOnMouseWheel(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
};
