// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "EndlessVendetta/EndlessVendettaCharacter.h"
#include "EndlessVendetta/EVGameInstance.h"
#include "EndlessVendetta/MainSaveGameClass.h"
#include "EndlessVendetta/PauseMenu/TabStructs/BountyTabInfo.h"
#include "EndlessVendetta/BountySystem/MainBountyClass.h"
#include "EndlessVendetta/BountySystem/SideBountyClass.h"
#include "EndlessVendetta/PauseMenu/BountiesTab.h"
#include "EndlessVendetta/PauseMenu/PauseMenuClass.h"
#include "EndlessVendetta/PauseMenu/QuitTab.h"
#include "BountyHunterCharacter.generated.h"

/**
 * 
 */
UCLASS()
class ENDLESSVENDETTA_API ABountyHunterCharacter : public AEndlessVendettaCharacter
{
	GENERATED_BODY()
// ------------------- ATTRIBUTES ------------------------------

	// Money Used for Buying things
	int Money = 0;

	// Favours used for making bounties easier
	int Favours = 0;
	
	// Array of Main Bounties' Classes in Order
	UPROPERTY(EditDefaultsOnly, Category = "Bounty Hunter")
	TArray<TSubclassOf<AMainBountyClass>> MainBountyClasses;
	
	// Reference to the Currently Active Main Bounty
	UPROPERTY()
	AMainBountyClass* CurrentMainBounty;

	// Index of Currently Active Main Bounty, Used for MainBountyClasses
	int CurrentMainBountyIndex = 0;
	
	// References to Currently Active Side Bounties
	TArray<ASideBountyClass*> CurrentSideBounties;

	// Name of open world, so that the correct bounties can be spawned based on level
	UPROPERTY(EditDefaultsOnly, Category = "Bounty Hunter")
	FString OpenWorldLevelName = "ControlTutorialLevel";

protected:	
	
public:



	
// ------------------- METHODS ---------------------------------
private:
	// Spawns Current Main Bounty along with its Side Bounties, and spawns its appropriate CP's based on level
	void SpawnMainBounty(UEVGameInstance* GI);
	
	// Collects Reward for Current Main Bounty and Increments the Main Bounty Index
	void CompleteCurrentMainBounty(UEVGameInstance* GI);

	// Collects Reward for Completing a Side Bounty
	UFUNCTION()
	void CompletedASideBounty(int CompletedSideBountiesUID);
	
	// Replaces Normal Bounty Info UI with Unique Game Over UI
	void AllBountiesCompleted();

	void SavePlayerMoneyAndFavours();

protected:
	// Called When Player Spawns
	virtual void BeginPlay() override;

	// Overridden to Setup up Pause Menu Inputs
	virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override;
	
	// Called When Actor destroyed or Removed from Level
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
	
public:
	// Used by Final Checkpoint to always load the Level set as the Open Level in here
	FString GetOpenWorldLevelName()
	{
		return OpenWorldLevelName;
	}

	// Public incase Money can be earned through outside sources in the future
	void EarnMoney(int MoneyEarned)
	{
		Money += MoneyEarned;
		SavePlayerMoneyAndFavours();
	}

	// Checks if player has enough money to spend, if true then spend money and return true
	bool SpendMoney(int MoneySpent)
	{
		if (MoneySpent > Money) return false;
		Money -= MoneySpent;
		SavePlayerMoneyAndFavours();
		return true;
	}

	// Public incase favours can be earned through outside sources in the future
	void EarnFavours(int FavoursEarned)
	{
		Favours += FavoursEarned;
		SavePlayerMoneyAndFavours();
	}

	// Checks if player has enough favours to spend, if true then spend favours and return true
	bool SpendFavours(int FavoursSpent)
	{
		if (FavoursSpent > Favours) return false;
		Favours -= FavoursSpent;
		SavePlayerMoneyAndFavours();
		return true;
	}



	
	
// ------------------- Pause Menu ---------------------------------
private:	
	// Input Action for Opening and Closing Pause Menu
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	UInputAction* PauseMenuAction;

	// Widget Class used to Spawn Pause Menu
	UPROPERTY(EditDefaultsOnly, Category = PauseMenu)
	TSubclassOf<UPauseMenuClass> PauseMenuWidgetClass;

	// Reference to Pause Menu Widget
	UPauseMenuClass* PauseMenu;
	
	// Widget Class used to Spawn Bounties Tab Widget
	UPROPERTY(EditDefaultsOnly, Category = "Pause Menu")
	TSubclassOf<UBountiesTab> BountyTabWidgetClass;

	// Widget Class used to Spawn Bounties Tab Widget
	UPROPERTY(EditDefaultsOnly, Category = "Pause Menu")
	TSubclassOf<UBountiesTab> BountyInProgressTabWidgetClass;

	// Widget Class used to Spawn Bounties Tab Widget
	UPROPERTY(EditDefaultsOnly, Category = "Pause Menu")
	TSubclassOf<UBountiesTab> TutorialBountyTabWidgetClass;
	
	// Reference to Bounty Tab Widget
	UPROPERTY()
	UBountiesTab* BountiesTab;

	// Widget Class used to Spawn Favours Tab Widget
	UPROPERTY(EditDefaultsOnly, Category = "Pause Menu")
	TSubclassOf<UTabWidget> FavoursTabWidgetClass;

	// Reference to Favours Tab Widget
	UPROPERTY()
	UTabWidget* FavoursTab;

	// Widget Class used to Spawn Navigation Tab Widget
	UPROPERTY(EditDefaultsOnly, Category = "Pause Menu")
	TSubclassOf<UTabWidget> NavigationTabWidgetClass;

	// Reference to Navigation Tab Widget
	UPROPERTY()
	UTabWidget* NavigationTab;

	// Widget Class used to Spawn Settings Tab Widget
	UPROPERTY(EditDefaultsOnly, Category = "Pause Menu")
	TSubclassOf<UTabWidget> SettingsTabWidgetClass;

	// Reference to Settings Tab Widget
	UPROPERTY()
	UTabWidget* SettingsTab;

	// Widget Class used to Spawn Quit Tab Widget
	UPROPERTY(EditDefaultsOnly, Category = "Pause Menu")
	TSubclassOf<UQuitTab> QuitTabWidgetClass;

	// Reference to Quit Tab Widget
	UPROPERTY()
	UQuitTab* QuitTab;

	// Creates and Stores References to each Pause Menu Tab on Begin Play
    void CreatePauseMenuTabs();

	// Open or Close the Pause Menu, Defaults to Opening Bounty Tab
    void TogglePauseMenu();

	// Opens Bounties Tab
	UFUNCTION()
	void OpenBountiesTab()
	{
		PauseMenu->OpenNewTab(BountiesTab);
	}

	// Opens Favours Tab
	UFUNCTION()
	void OpenFavoursTab()
	{
		PauseMenu->OpenNewTab(FavoursTab);
	}

	// Opens Navigation Tab
	UFUNCTION()
	void OpenNavigationTab()
	{
		PauseMenu->OpenNewTab(NavigationTab);
	}

	// Opens Settings Tab
	UFUNCTION()
	void OpenSettingsTab()
	{
		PauseMenu->OpenNewTab(SettingsTab);
	}

	// Opens Quit Tab
	UFUNCTION()
	void OpenQuitTab()
	{
		PauseMenu->OpenNewTab(QuitTab);
	}
	
	FBountyTabInfo BountyTabInfo;

	FMainBountyStruct MainBountyStruct;

	TArray<FSideBountyStruct> SideBountyStructs;

	void UpdateBountyTabInfo()
	{
		if (!IsValid(BountiesTab)) return;
		BountyTabInfo.MainBountyStruct = MainBountyStruct;
		BountyTabInfo.SideBountyStructs = SideBountyStructs;
		
		BountiesTab->UpdateBountyTab(BountyTabInfo);
	}

	UFUNCTION()
	void ReturnToOpenWorldEarly();

	void DeActivateAllBounties()
	{
		CurrentMainBounty->DeActivateFirstCheckpoint();
		for (auto SideBounty : CurrentSideBounties)
		{
			SideBounty->DeActivateFirstCheckpoint();
		}
	}

	UFUNCTION()
	void TrackMainBounty()
	{
		DeActivateAllBounties();
		CurrentMainBounty->ActivateFirstCheckpoint();
	}

	UFUNCTION()
	void TrackSideBounty(int SideBountyUID)
	{
		DeActivateAllBounties();
		for (auto SideBounty : CurrentSideBounties)
		{
			if (SideBounty->GetUniqueID() == SideBountyUID)
			{
				SideBounty->ActivateFirstCheckpoint();
				break;
			}
		}
	}
};
