// Project Sword & Gun Copyright © 2021 Kevin Poretti

#pragma once

#include "CoreMinimal.h"

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

#include "SNGProtagonist.generated.h"

USTRUCT(BlueprintType)
struct FMeleeAttackData
{
	GENERATED_BODY()

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

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Motion")
	UCurveVector* RootMotionCurve;
};

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

public:
	ASNGProtagonist(const FObjectInitializer& ObjectInitializer);

	void MoveForward(float Value);

	void MoveRight(float Value);

	UFUNCTION(BlueprintCallable)
	void DoJump();

	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);

	/**
	 *	Performs an air dash
	 *
	 *	NOTE(kevin): For now this only increments the CurrNumAirDashes value. All of the current air dash functionality
	 *	is in blueprints and I don't feel like moving it over to C++.
	 */
	UFUNCTION(BlueprintCallable)
	void DoAirDash();
	
	/**
	 *	Resets the number of current number of air dashes to zero. For example, when
	 *	the player lands on the ground when they were previously in the air or when they reload in the air.
	 */
	UFUNCTION(BlueprintCallable)
	void ResetAirDashCount();

	/**
	 *	Returns true if the current number of air dashes does not exceed the maximum amount of allowed air dashes.
	 *
	 *	@returns true if the player can air dash (CurrNumAirDashes < MaxNumAirDashes) and false otherwise
	 */
	UFUNCTION(BlueprintCallable)
	bool CanAirDash() const;
	
	UFUNCTION(BlueprintCallable)
	void CycleRangedWeapon();

	UFUNCTION(BlueprintCallable)
    void CycleMeleeWeapon();
	
	void EquipWeapon(ASNGWeaponBase* WeaponToEquip, FName HandSocket);
	
	virtual ASNGWeaponBase* GetCurrentWeapon_Implementation() override;
	
protected:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
	UCameraComponent* CameraComponent;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
	USpringArmComponent* SpringArmComponent;
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
	USNGWeaponInventoryComponent* WeaponInventoryComponent;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Sockets")
	FName GunHandSocket;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Sockets")
	FName SwordHandSocket;
	
	UPROPERTY(BlueprintReadWrite)
	bool bIsAiming;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Camera")
	float AimFOV;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Camera", meta = (ClampMin = 0.1, ClampMax = 120))
	float AimSpeed; 
    
	float DefaultFOV;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Soft Lock")
	float SoftLockHalfAngle;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Soft Lock")
	float SoftLockRange;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Soft Lock")
	int NumSoftLockLineTraces;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Rotate Towards Target")
	float DegreesPerSecond;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Rotate Towards Target")
	float MaxRotation;
	
	TArray<AActor*> SoftLockedActors;

	AActor* ClosestActor;
	float DistFromClosestActor;
	float AngleFromClosestActor;
	
	/**
	 * NOTE(kevin): Are these still being used anymore?
	 */
	float LastForwardAxis;
	float LastRightAxis;
	
	UPROPERTY(BlueprintReadWrite)
	bool bIsMeleeAttackComboReset;

	UPROPERTY(BlueprintReadWrite)
	bool bDoesMovementInputCancelAnimMontage;

	/** Maximum number of air dashes a player is allowed do in the air */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Air Dash")
	int32 MaxNumAirDashes;
	
	UPROPERTY(BlueprintReadWrite)
	int32 CurrNumAirDashes;
	
	//UFUNCTION(BlueprintCallable)
	//FVector GetInputAsWorldDirection(float ForwardAxisValue, float RightAxisValue);

	void GetClosestSoftLockedActor();
	
	virtual FVector GetPawnViewLocation() const override;
	
	virtual void BeginPlay() override;
	
	virtual void Tick(float DeltaSeconds) override;
};
