// Oleg Petruny proprietary.

#pragma once

#include "GameFramework/PlayerController.h"

#include "CustomPlayerController.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerAnyKeyPressedDelegate, FKey, key);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPlayerAnyKeyReleasedDelegate, FKey, key);

/**
 * De-facto wrapper/interface of all usefull shortcuts and automatization around input system.
 * Append new input context here for auto init on BeginPlay and apply user input settings.
 * Also, has delegates onAnyKeyPressed/Released.
 */
UCLASS()
class ACustomPlayerController : public APlayerController
{
    GENERATED_BODY()

public:
    UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Custom Player Controller"))
    static ACustomPlayerController* Get() { return instance; }
    UFUNCTION(BlueprintPure)
    static class UEnhancedInputComponent* GetInput() { return input; }
    UFUNCTION(BlueprintPure)
    static class UEnhancedInputLocalPlayerSubsystem* GetInputSubsystem() { return subsystem; }

    UFUNCTION(BlueprintCallable)
    static void AppendInputContext(TSoftObjectPtr<class UInputMappingContext> context);

    FPlayerAnyKeyPressedDelegate onAnyKeyPressed;
    FPlayerAnyKeyReleasedDelegate onAnyKeyReleased;

protected:
    virtual void BeginPlay() override;
    virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

private:
    static void ApplyMouseSettings(TSoftObjectPtr<class UInputMappingContext>& context);

    void OnAnyKeyPressed(FKey key);
    void OnAnyKeyReleased(FKey key);

    static ACustomPlayerController* instance;
    static class UEnhancedInputLocalPlayerSubsystem* subsystem;
    static class UEnhancedInputComponent* input;
    static TSet<TSoftObjectPtr<class UInputMappingContext>> contexts;
    /** Contexts added before game instance fully initialized cannot apply game settings because not fully initialized game */
    static TSet<TSoftObjectPtr<class UInputMappingContext>> contextsBeforeInit;
};
