// Project Sword & Gun Copyright © 2021 Kevin Poretti

#pragma once

#include "CoreMinimal.h"

#include "Camera/CameraComponent.h"
#include "Characters/SNGCharacterBase.h"
#include "Components/SNGStateMachineComponent.h"
#include "Components/SNGWeaponInventoryComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "Weapons/SNGWeaponBase.h"


#include "SNGProtagonist.generated.h"

USTRUCT(BlueprintType)
struct FMeleeAttackData
{
	GENERATED_BODY()

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Animation")
	UAnimMontage* AttackMontage;
};

/**
 * 
 */
UCLASS()
class SWORDNGUN_API ASNGProtagonist : public ASNGCharacterBase, public ISNGEventProcessorInterface
{
	GENERATED_BODY()

public:
	ASNGProtagonist();

	void MoveForward(float Value);

	void MoveRight(float Value);

	UFUNCTION(BlueprintCallable)
	void DoJump();

	UFUNCTION(BlueprintCallable)
	float Dash();

	UFUNCTION(BlueprintCallable)
	float MeleeAttack(FMeleeAttackData MeleeAttackData);

	UFUNCTION(BlueprintGetter)
	bool IsMeleeAttackComboReset();

	UFUNCTION(BlueprintCallable)
	void SetMeleeAttackCombo(bool IsComboReset);

	UFUNCTION(BlueprintGetter)
	bool DoesMovementInputCancelAnimMontage();

	UFUNCTION(BlueprintCallable)
	void SetDoesMovementInputCancelAnimMontage(bool DoesMovementCancelMontage);
	
	/**
	 * The state machine will be handling most if not all of the states
	 * we simply wrap the state machine's push event implementation since most
	 * objects that will want to push events to the protagonist will have a reference
	 * to the protag itself rather than the protag's state machine
	 */ 
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	bool PushEvent(FSNGEvent Event);
	
protected:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
	UCameraComponent* CameraComponent;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
	USpringArmComponent* SpringArmComponent;
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
	USNGStateMachineComponent* StateMachineComponent;
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
	USNGWeaponInventoryComponent* WeaponInventoryComponent;
	
	/** 
	 * TODO(kevin): would like to take this out eventually.
	 * We probably want a generic function that plays montages on a character
	 * and call that from the state's OnEnter event.
	 * The state should have a reference to the dash montage, not the character.
	 */ 
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Animations")
	UAnimMontage* DashMontage;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Sockets")
	FName HandSocket;
	
	/**
	 * NOTE(kevin): Are these still being used anymore?
	 */
	float LastForwardAxis;
	float LastRightAxis;
	
	UPROPERTY(BlueprintReadWrite)
	bool bIsMeleeAttackComboReset;

	UPROPERTY(BlueprintReadWrite)
	bool bDoesMovementInputCancelAnimMontage;
	
	FVector GetInputAsWorldDirection();

	FVector GetInputAsWorldDirection(float ForwardAxisValue, float RightAxisValue);

	virtual void BeginPlay() override;
	
	virtual void Tick(float DeltaSeconds) override;
};
