#pragma once

#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "Http.h"
#include "SocketIONative.h"
#include "GenericStructs.h"
#include "CMGameInstance.generated.h"

/**
 * 
 */
UCLASS()
class CORRUPTEDMEMORY_API UCMGameInstance : public UGameInstance
{
	GENERATED_BODY()

public:
	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLoginComplete, const bool, bWasSuccessful);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRegisterComplete, const bool, bWasSuccessful);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLogoutComplete, const bool, bWasSuccessful);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnCreateLobbyComplete, const bool, bWasSuccessful);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnJoinLobbyComplete, const bool, bWasSuccessful);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLeaveLobbyComplete, const bool, bWasSuccessful);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnGetPlayersInLobbyComplete, const bool, bWasSuccessful);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnServerLobbyListComplete, const bool, bWasSuccessful);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnGetLobbyByID, const bool, bWasSuccessful, const FString, LobbyID, const int, MaxPlayers);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerJoin, const FString, PlayerName);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerLeave, const FString, PlayerName);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerReady, const FString, PlayerName);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlayerUnReady, const FString, PlayerName);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnServerClose, const FString, Message);

	UPROPERTY(BlueprintAssignable, Category = "Account")
	FOnLoginComplete OnLoginComplete;
	UPROPERTY(BlueprintAssignable, Category = "Account")
	FOnRegisterComplete OnRegisterComplete;
	UPROPERTY(BlueprintAssignable, Category = "Account")
	FOnLogoutComplete OnLogoutComplete;
	UPROPERTY(BlueprintAssignable, Category = "Lobby")
	FOnCreateLobbyComplete OnCreateLobbyComplete;
	UPROPERTY(BlueprintAssignable, Category = "Lobby")
	FOnJoinLobbyComplete OnJoinLobbyComplete;
	UPROPERTY(BlueprintAssignable, Category = "Lobby")
	FOnLeaveLobbyComplete OnLeaveLobbyComplete;
	UPROPERTY(BlueprintAssignable, Category = "Lobby")
	FOnGetPlayersInLobbyComplete OnGetPlayersInLobbyComplete;
	UPROPERTY(BlueprintAssignable, Category = "Lobby")
	FOnServerLobbyListComplete OnServerLobbyListComplete;
	UPROPERTY(BlueprintAssignable, Category = "Lobby")
	FOnGetLobbyByID OnGetLobbyByID;
	UPROPERTY(BlueprintAssignable, Category = "Lobby")
	FOnPlayerJoin OnPlayerJoin;
	UPROPERTY(BlueprintAssignable, Category = "Lobby")
	FOnPlayerLeave OnPlayerLeave;
	UPROPERTY(BlueprintAssignable, Category = "Lobby")
	FOnPlayerReady OnPlayerReady;
	UPROPERTY(BlueprintAssignable, Category = "Lobby")
	FOnPlayerUnReady OnPlayerUnReady;
	UPROPERTY(BlueprintAssignable, Category = "Lobby")
	FOnServerClose OnServerClose;

	UPROPERTY(BlueprintReadOnly, Category = "Account")
	FString AccountUsername = "Bruh";
	UPROPERTY(BlueprintReadOnly, Category = "Account")
	FString JwtToken;
	UPROPERTY(BlueprintReadOnly, Category = "Account")
	int32 PlayerIndex = 0;

	UPROPERTY(BlueprintReadOnly, Category = "Lobby")
	FString ServerFQDN = "cm.api.philipwhite.dev";
	UPROPERTY(BlueprintReadOnly, Category = "Lobby")
	FString JoinedLobbyID;
	UPROPERTY(BlueprintReadOnly, Category = "Lobby")
	int ServerPort;
	UPROPERTY(BlueprintReadOnly, Category = "Lobby")
	TArray<FPlayerInLobby> PlayersInLobby;
	UPROPERTY(BlueprintReadOnly, Category = "Lobby")
	TArray<FServerLobby> ServerLobbies;

	UFUNCTION(BlueprintCallable, Category = "Account")
	void Login(const FString& Username, const FString& Password);
	UFUNCTION(BlueprintCallable, Category = "Account")
	void Register(const FString& Username, const FString& Password);
	UFUNCTION(BlueprintCallable, Category = "Account")
	void Logout();
	UFUNCTION(BlueprintCallable, Category = "Lobby")
	void CreateLobby(const int MaxPlayers);
	UFUNCTION(BlueprintCallable, Category = "Lobby")
	void JoinLobby(const FString LobbyID);
	UFUNCTION(BlueprintCallable, Category = "Lobby")
	void LeaveLobby();
	UFUNCTION(BlueprintCallable, Category = "Lobby")
	void GetPlayerLobbyList();
	UFUNCTION(BlueprintCallable, Category = "Lobby")
	void GetServerLobbyList();
	UFUNCTION(BlueprintCallable, Category = "Lobby")
	void GetLobbyByID(const FString LobbyID);
	UFUNCTION(BlueprintCallable, Category = "Lobby")
	void ReadyUp();
	UFUNCTION(BlueprintCallable, Category = "Lobby")
	void UnReady();
	UFUNCTION(BlueprintCallable, Category = "Lobby")
	void StartGame();


	virtual void Init() override;
	virtual void Shutdown() override;
	TSharedPtr<FSocketIONative> Socket;

private:
	FString LobbyAPI = "https://cm.api.philipwhite.dev/api";
	void OnRequestToLoginComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
	void OnRequestToRegisterComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful) const;
	void OnRequestToLogoutComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
	void OnRequestToCreateLobbyComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
	void OnRequestToJoinLobbyComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
	void OnRequestToLeaveLobbyComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
	void OnRequestToGetLobbyPlayersComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
	void OnRequestToGetServerLobbyListComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
	void OnRequestToGetLobbyByIDComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
};
