 #pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "PragmaPtr.h"
#include "PragmaGameInstanceSubsystem.h"
#include "PragmaMessageMetadata.h"
#include "PragmaResult.h"
#include "Blueprint/UserWidget.h"
#include "Components/Button.h"
#include "Components/EditableText.h"
#include "Components/TextBlock.h"
#include "Dto/PragmaGameInstanceExtDto.h"
#include "Dto/PragmaPlayerDataServiceRpcDto.h"
#include "Pragma/Common/GameInstance/PragmaGameInstance.h"
#include "Pragma/Common/Party/PragmaParty.h"
#include "MyPlayerController.generated.h"

// Forward declares Pragma pointer types using the PRAGMA_FWD macro supplied by `PragmaPtr.h`.
PRAGMA_FWD(FPlayer);

UCLASS()
class SAMPLEGAME_API AMyPlayerController : public APlayerController
{
	GENERATED_BODY()
	
public:
	void InitializePragmaApis();
	void OnPartyChangedTriggered(const FPragmaParty& PragmaParty);
	void OnEnteredMatchmakingTriggered();
	void OnHostConnectionDetailsReceivedTriggerred(const FPragmaGameInstance& PragmaGameInstance);
	void OnAddedToGameTriggered(const FPragmaGameInstance& PragmaGameInstance);
	void OnGameEndedTriggerred(const FString& GameInstanceId, const FPragma_GameInstance_ExtGameEnded& Pragma_GameInstance_ExtGameEnded);
	void OnPlayerDataUpdated();
	void OnPlayerDataUpdatedV1(FPragma_PlayerData_PlayerDataUpdatedV1Notification Notification, const FPragmaMessageMetadata& PragmaMessageMetadata);
	void OnReconnectedTriggered();
	void SetupPragmaPlayerDataSubscriptions();
	void SetupPragmaSubscriptions();
	void SetupPragmaGameInstanceApiSubscriptions();
	void SetupPragmaPartyApiSubscriptions();

	// Called when the `AMyPlayerController` is created.
	UFUNCTION()
	virtual void BeginPlay() override;
	UFUNCTION()
	void OnCrashAppButtonClicked();
	UFUNCTION()
	void OnLoginButtonClicked();
	UFUNCTION()
	void OnLoginSteamButtonClicked();
	UFUNCTION()
	void OnCreatePartyButtonClicked();
	UFUNCTION()
	void OnSetPlayerIsReadyButtonClicked();
	UFUNCTION()
	void OnEnterMatchmakingButtonClicked();
	UFUNCTION()
	void OnCommunicateWithGameServerButtonClicked();
	UFUNCTION()
	void OnShowPlayerCurrencyButtonClicked();
	UFUNCTION()
	void OnGrantMeCurrencyButtonClicked();

	UFUNCTION()
	void OnShowListOfGameServersButtonClicked();
	UFUNCTION()
	void OnJoinGameServerButtonClicked();
	
	UFUNCTION()
	void FindButtonsAndStuff();
	UFUNCTION()
	void UpdatePlayerCurrencyBalance();

	UFUNCTION(Server, Reliable)
	void CommunicateWithGameServer(const FString& Message);
	
	UFUNCTION(Server, Reliable)
	void GrantPlayerCurrencyGameServer(const FString& PlayerId);
	
	UFUNCTION(Exec)
	void LogIn(const FString& Username);

	UFUNCTION(Exec)
	void LogOut();

	UFUNCTION(Exec)
	void LogInSteam();
	FString GetSteamToken();
	
private:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI", meta = (AllowPrivateAccess = "true"))
	TSubclassOf<UUserWidget> MainUIClass;

	UPROPERTY()
	UButton* CrashAppButton;
	
	UPROPERTY()
	UButton* LoginButton;

	UPROPERTY()
	UButton* LoginSteamButton;

	UPROPERTY()
	UButton* CreatePartyButton;
	
	UPROPERTY()
	UButton* SetPlayerIsReadyButton;
	
	UPROPERTY()
	UButton* EnterMatchmakingButton;
	
	UPROPERTY()
	UButton* CommunicateWithGameServerButton;

	UPROPERTY()
	UButton* ShowCurrencyButton;

	UPROPERTY()
	UButton* GrantMeCurrencyButton;
	
	UPROPERTY()
	UEditableText* UsernameEditableTextBox;

	UPROPERTY()
	UEditableText* CommunicateMessageEditableTextBox;

	UPROPERTY()
	UTextBlock* ShowCurrencyBalanceText;

		
	UPROPERTY()
	UButton* ShowListOfGameServersButton;
	
	UPROPERTY()
	UButton* JoinGameServerButton;
	
	UPROPERTY()
	UEditableText* GameInstanceIdEditableTextBox;

	// Weak pointer to our Pragma Player owned by the PragmaLocalPlayerSubsystem.
	Pragma::FPlayerPtr PragmaPlayer;

	void HandleLoggedIn(const TPragmaResult<>& Result);
	void HandleLoggedOut();
};
