#include "ZeusPlayerController.h"

#include "Blueprint/UserWidget.h"
#include "Components/InputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "Engine/GameInstance.h"
#include "Engine/LocalPlayer.h"
#include "Framework/Commands/InputChord.h"
#include "InputMappingContext.h"
#include "UObject/ConstructorHelpers.h"
#include "Widgets/Input/SVirtualJoystick.h"
#include "ZMMO.h"
#include "UI/InGame/UIInGameFlowSubsystem.h"
#include "UI/InGameTypes.h"

AZeusPlayerController::AZeusPlayerController()
{
	// Defaults dos Input Mapping Contexts (alinhados ao ZClientMMO). Permitem
	// instanciar AZeusPlayerController directamente como
	// `PlayerControllerClass` do AZeusGameMode sem exigir um BP filho. Se o
	// projeto adicionar mais IMCs, podemos extender via BP filho ou via
	// arquivos de Config (UPROPERTY EditAnywhere abaixo).
	static ConstructorHelpers::FObjectFinder<UInputMappingContext> DefaultImc(
		TEXT("/Game/Input/IMC_Default.IMC_Default"));
	static ConstructorHelpers::FObjectFinder<UInputMappingContext> MouseLookImc(
		TEXT("/Game/Input/IMC_MouseLook.IMC_MouseLook"));

	if (DefaultImc.Succeeded())
	{
		DefaultMappingContexts.Add(DefaultImc.Object);
	}
	if (MouseLookImc.Succeeded())
	{
		MobileExcludedMappingContexts.Add(MouseLookImc.Object);
	}
}

void AZeusPlayerController::BeginPlay()
{
	Super::BeginPlay();

	if (IsLocalPlayerController())
	{
		// Limpa estado de input herdado da UI do FrontEnd (UIManagerSubsystem
		// e LocalPlayerSubsystem — sobrevive ao travel, e o controller anterior
		// (AZeusFrontEndPlayerController) tinha setado FInputModeUIOnly +
		// bShowMouseCursor=true). Sem este reset, WASD/Look podem nao chegar
		// ao pawn porque o Slate ainda esta com foco no widget antigo.
		FInputModeGameOnly InputMode;
		InputMode.SetConsumeCaptureMouseDown(true);
		SetInputMode(InputMode);
		bShowMouseCursor = false;
		FlushPressedKeys();
	}

	if (ShouldUseTouchControls() && IsLocalPlayerController())
	{
		MobileControlsWidget = CreateWidget<UUserWidget>(this, MobileControlsWidgetClass);
		if (MobileControlsWidget)
		{
			MobileControlsWidget->AddToPlayerScreen(0);
		}
		else
		{
			UE_LOG(LogZMMO, Error, TEXT("Could not spawn mobile controls widget."));
		}
	}
}

void AZeusPlayerController::SetupInputComponent()
{
	Super::SetupInputComponent();

	if (!IsLocalPlayerController())
	{
		return;
	}

	if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
	{
		for (UInputMappingContext* CurrentContext : DefaultMappingContexts)
		{
			Subsystem->AddMappingContext(CurrentContext, 0);
		}

		if (!ShouldUseTouchControls())
		{
			for (UInputMappingContext* CurrentContext : MobileExcludedMappingContexts)
			{
				Subsystem->AddMappingContext(CurrentContext, 0);
			}
		}
	}

	// Hotkey global Alt+A -> toggle StatusWindow. Uso InputComponent legacy
	// (BindKey com FInputChord) pra nao depender de assets InputAction.
	// Migrar pra Enhanced Input (IA_OpenStatus, IA_OpenInventory, etc.) quando
	// vier outro menu (Inventory I, SkillTree K).
	if (InputComponent)
	{
		FInputKeyBinding& Binding = InputComponent->BindKey(
			FInputChord(EKeys::A, /*bShift*/ false, /*bCtrl*/ false, /*bAlt*/ true, /*bCmd*/ false),
			IE_Pressed,
			this, &AZeusPlayerController::ToggleStatusWindow);
		Binding.bConsumeInput = true;
		Binding.bExecuteWhenPaused = true;  // dispara mesmo com StatusWindow aberto (CommonUI menu mode)

		// Hotkey J -> toggle JobChangePanel (Jobs.1).
		FInputKeyBinding& JobBinding = InputComponent->BindKey(
			FInputChord(EKeys::J, /*bShift*/ false, /*bCtrl*/ false, /*bAlt*/ false, /*bCmd*/ false),
			IE_Pressed,
			this, &AZeusPlayerController::ToggleJobChangePanel);
		JobBinding.bConsumeInput = true;
		JobBinding.bExecuteWhenPaused = true;
	}
}

void AZeusPlayerController::ToggleStatusWindow()
{
	if (UGameInstance* GI = GetGameInstance())
	{
		if (UUIInGameFlowSubsystem* Flow = GI->GetSubsystem<UUIInGameFlowSubsystem>())
		{
			Flow->ToggleScreen(EZeusInGameUIState::StatusWindow);
		}
	}
}

void AZeusPlayerController::ToggleJobChangePanel()
{
	if (UGameInstance* GI = GetGameInstance())
	{
		if (UUIInGameFlowSubsystem* Flow = GI->GetSubsystem<UUIInGameFlowSubsystem>())
		{
			Flow->ToggleScreen(EZeusInGameUIState::JobChangePanel);
		}
	}
}

bool AZeusPlayerController::ShouldUseTouchControls() const
{
	return SVirtualJoystick::ShouldDisplayTouchInterface() || bForceTouchControls;
}
