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


#include "FayePlayerController.h"
#include "EnhancedInputComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Faye/GameObjects/PlayerCharacter.h"
#include "EnhancedInputSubsystems.h"
#include "FayeCameraManager.h"
#include "SUDSLibrary.h"
#include "Faye/UI/MainGameWidget.h"
#include "Faye/GameObjects/ShelfActor.h"
#include "Faye/UI/Controller/ShelvesStackingController.h"

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

	if (UEnhancedInputComponent *PlayerEnhancedInputComponent = Cast<UEnhancedInputComponent>(InputComponent))
	{
		if (MoveInputAction)
		{
			PlayerEnhancedInputComponent->BindAction(MoveInputAction, ETriggerEvent::Triggered, this, &AFayePlayerController::OnMove);
		}
		if (LookInputAction)
		{
			PlayerEnhancedInputComponent->BindAction(LookInputAction, ETriggerEvent::Triggered, this, &AFayePlayerController::OnLook);
		}
		if (ZoomInputAction)
		{
			PlayerEnhancedInputComponent->BindAction(ZoomInputAction, ETriggerEvent::Triggered, this, &AFayePlayerController::OnZoom);
		}
		if (InteractInputAction)
		{
			PlayerEnhancedInputComponent->BindAction(InteractInputAction, ETriggerEvent::Started, this, &AFayePlayerController::OnInteract);
		}
		
		if (PhoneInputAction)
		{
			PlayerEnhancedInputComponent->BindAction(PhoneInputAction, ETriggerEvent::Started, this, &AFayePlayerController::OnPhoneToggle);
		}
		if (OptionsInputAction)
		{
			PlayerEnhancedInputComponent->BindAction(OptionsInputAction, ETriggerEvent::Started, this, &AFayePlayerController::OnOptionsToggle);
		}
		
		if (ShelveStackingBookConfirmAction)
		{
			PlayerEnhancedInputComponent->BindAction(ShelveStackingBookConfirmAction, ETriggerEvent::Started, this, &AFayePlayerController::OnShelveBookPlacementConfirm);
		}
		
		if (CoffeeMakingGrabAction)
		{
			PlayerEnhancedInputComponent->BindAction(CoffeeMakingGrabAction, ETriggerEvent::Started, this, &AFayePlayerController::OnCoffeeMakingGrabActionPress);
			PlayerEnhancedInputComponent->BindAction(CoffeeMakingGrabAction, ETriggerEvent::Completed, this, &AFayePlayerController::OnCoffeeMakingGrabActionRelease);
		}
	}
}

void AFayePlayerController::ClientRestart_Implementation(class APawn* NewPawn)
{
	Super::ClientRestart_Implementation(NewPawn);
		
	if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
	{
		Subsystem->ClearAllMappings();

		Subsystem->AddMappingContext(MovementInputMappingContext, 1);
		Subsystem->AddMappingContext(UiInputMappingContext, 2);
		//Subsystem->AddMappingContext(UiInputMappingContext, 3);
		//Subsystem->AddMappingContext(ActionContext, 4);
	}
}

void AFayePlayerController::CloseWidget(UFayeBaseWidget* Widget)
{
	Widget->ToggleWidget(false);
	ActiveWidgets.Remove(Widget);
	if (ActiveWidgets.IsEmpty())
	{
		SetShowMouseCursor(false);
		SetInputMode(FInputModeGameOnly());
		bInMenu = false;
		SetPause(false);
	}
}

void AFayePlayerController::ToggleCoffeeMaking(bool bActive)
{
	if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
	{
		if (bActive)
		{
			Subsystem->AddMappingContext(CoffeeMakingMappingContext, 12);
		}
		else
		{
			Subsystem->RemoveMappingContext(CoffeeMakingMappingContext);
		}
	}
}

void AFayePlayerController::BeginPlay()
{
	Super::BeginPlay();
	
	PlayerCharacter = Cast<APlayerCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
	FayeCameraManager = Cast<AFayeCameraManager>(PlayerCameraManager);
	
	MainGameWidget = CreateWidget<UMainGameWidget>(this, MainWidgetClass, "MainGameWidget");
	MainGameWidget->AddToViewport();
}

void AFayePlayerController::OpenGenericWidget(UFayeBaseWidget* Widget)
{
	ActiveWidgets.Add(Widget);
	SetShowMouseCursor(true);
	SetInputMode(FInputModeGameAndUI());
	bInMenu = true;
}

void AFayePlayerController::StartDialogueFromScript(UObject* DialogueParticipant, USUDSScript* Script)
{
	USUDSDialogue* DialogueObject = USUDSLibrary::CreateDialogueWithParticipant(DialogueParticipant, Script, DialogueParticipant, true);
	StartDialogue(DialogueParticipant, DialogueObject);
}

void AFayePlayerController::StartDialogue(UObject* DialogueParticipant, USUDSDialogue* Dialogue)
{
	MainGameWidget->ToggleDialogueWidget(true, FDialogueWidgetPayload(Dialogue));
	FInputModeGameAndUI InputMode;
	InputMode.SetHideCursorDuringCapture(false);
	SetInputMode(InputMode);
	SetShowMouseCursor(true);
}

void AFayePlayerController::EndDialogue()
{
	MainGameWidget->ToggleDialogueWidget(false, nullptr);
	SetInputMode(FInputModeGameOnly());
	SetShowMouseCursor(false);
}

void AFayePlayerController::OpenOptionsWidget()
{
	OpenGenericWidget(MainGameWidget->GetOptionsWidget());
	MainGameWidget->ToggleOptionsWidget(true);
}

void AFayePlayerController::CloseOptionsWidget()
{
	MainGameWidget->ToggleOptionsWidget(false);
	CloseWidget(MainGameWidget->GetOptionsWidget());
}

void AFayePlayerController::ClosePhoneWidget()
{
	MainGameWidget->TogglePhoneWidget(false);
	CloseWidget(MainGameWidget->GetPhoneWidget());
}

void AFayePlayerController::OpenShelvesStackingWidget(AShelfActor* ShelfActorRef)
{
	OpenGenericWidget(MainGameWidget->GetShelvesStackingWidget());
	FShelvesStackingSetupPayload Payload;
	Payload.ShelfActorRef = ShelfActorRef;
	MainGameWidget->ToggleShelvesStackingWidget(true, Payload);
	OnToggleShelveStacking.Broadcast(true);
	
	if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
	{
		Subsystem->AddMappingContext(ShelveStackingMappingContext, 99);
	}
	ShelfRef = ShelfActorRef;
}

void AFayePlayerController::CloseShelvesStackingWidget()
{
	MainGameWidget->ToggleShelvesStackingWidget(false, FShelvesStackingSetupPayload());
	CloseWidget(MainGameWidget->GetShelvesStackingWidget());
	OnToggleShelveStacking.Broadcast(false);
	
	if (UEnhancedInputLocalPlayerSubsystem *Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer()))
	{
		Subsystem->RemoveMappingContext(ShelveStackingMappingContext);
	}
	ShelfRef = nullptr;
}

void AFayePlayerController::OnMove(const FInputActionValue& Value)
{
	const FVector2D AnalogueValue = Value.Get<FInputActionValue::Axis2D>();

	const FVector ForwardVec = PlayerCharacter->GetActorForwardVector();
	const FVector RightVec = PlayerCharacter->GetActorRightVector();
	
	PlayerCharacter->AddMovementInput(ForwardVec, AnalogueValue.Y);
	PlayerCharacter->AddMovementInput(RightVec, AnalogueValue.X);
}

void AFayePlayerController::OnLook(const FInputActionValue& Value)
{
	FVector2D AnalogueValue = Value.Get<FInputActionValue::Axis2D>();

	GetPawn()->AddControllerYawInput(AnalogueValue.X);
	GetPawn()->AddControllerPitchInput(AnalogueValue.Y);
}

void AFayePlayerController::OnZoom(const FInputActionValue& Value)
{
	float AnalogueValue = Value.Get<FInputActionValue::Axis1D>();
	FayeCameraManager->ZoomIn(AnalogueValue);
}

void AFayePlayerController::OnInteract(const FInputActionValue& Value)
{
	PlayerCharacter->InteractWithObject();
}

void AFayePlayerController::OnPhoneToggle(const FInputActionValue& Value)
{
	if (!MainGameWidget->IsPhoneOpen())
	{
		OpenGenericWidget(MainGameWidget->GetPhoneWidget());
		MainGameWidget->TogglePhoneWidget(true);
	}
	else
	{
		void ClosePhoneWidget();
	}
}

void AFayePlayerController::OnOptionsToggle(const FInputActionValue& Value)
{
	if (!MainGameWidget->IsOptionsOpen())
	{
		OpenOptionsWidget();
	}
	else
	{
		CloseOptionsWidget();
	}
}

void AFayePlayerController::OnShelveBookPlacementConfirm(const FInputActionValue& Value)
{
	if (ShelfRef)
	{
		ShelfRef->PlaceBook();
	}
}

void AFayePlayerController::OnCoffeeMakingGrabActionPress(const FInputActionValue& Value)
{
	OnCoffeeMakingAction_GrabStarted.Broadcast();
}

void AFayePlayerController::OnCoffeeMakingGrabActionRelease(const FInputActionValue& Value)
{
	OnCoffeeMakingAction_GrabRelease.Broadcast();
}

