// Project Sword & Gun Copyright © 2021 Kevin Poretti

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "SNGCharacterMovementComponent.generated.h"

/**
 *	Class that extends UE CharacterMovementComponent to add SNG specific functionality
 *
 *	Allows for different gravity scales, friction, and walk speeds when performing certain actions. This class will also
 *	lerp and changed values 
 */
UCLASS()
class SWORDNGUN_API USNGCharacterMovementComponent : public UCharacterMovementComponent
{
	GENERATED_BODY()

public:
	USNGCharacterMovementComponent();

	/**
	 *	Instantly sets all movement parameters to their defaults values (i.e. ground friction to DefaultGroundFriction,
	 *	MaxWalkSpeed to DefaultMaxWalkSpeed, etc.)
	 */
	UFUNCTION(BlueprintCallable)
	void RestoreMovementDefaults();
	
protected:
	/** Default friction when not performing any special actions and on the ground */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Ground Defaults", meta=(ClampMin="0", UIMin="0"))
	float DefaultGroundFriction;
	
	/** Default ground walk speed when not performing any special actions */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Ground Defaults", meta=(ClampMin="0", UIMin="0"))
	float DefaultMaxWalkSpeed;

	/** Ground walk speed when firing a ranged weapon */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Ground Defaults", meta=(ClampMin="0", UIMin="0"))
	float FiringMaxWalkSpeed;

	/** Ground walk speed when reloading a ranged weapon */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Ground Defaults", meta=(ClampMin="0", UIMin="0"))
	float ReloadingMaxWalkSpeed;

	/** Ground walk speed when sprinting */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Ground Defaults", meta=(ClampMin="0", UIMin="0"))
	float SprintingMaxWalkSpeed;

	/** Gravity scale when not performing any special actions */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0"))
	float DefaultGravityScale;

	/** Force to continuously apply to character when they are holding the jump button */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0"))
	float JumpForce;

	/** Timer that counts down */
	UPROPERTY(BlueprintReadWrite);
	float JumpTimer;

	/** Minimum height a character must reach before jump force is no longer applied even if the jump input is not being held */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0"))
	float MinJumpHeight;

	/** Max time the jump button can be held to give character upward velocity */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0"))
	float MaxJumpTime;

	/** How much to dampen lateral velocities at the start of a jump */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0"))
	float LateralVelocityDampening;
	
	/**
	 *	Sets up character velocities and jump parameters like the jump timer	
	 */
	UFUNCTION(BlueprintCallable)
	void StartJump();

	/**
	 *	Continuously applies an upward force to the character as the jump button is held down 
	 */
	UFUNCTION(BlueprintCallable)
	void AddJumpForce();
	
	/** Default friction when not performing any special actions and in the air */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0"))
	float DefaultAirFriction;

	/** Default friction when not performing any special actions and in the air */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0"))
	float DefaultAirControl;

	/** Minimum distance from the ground a character has to be to be able to perform an air dash */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0"))
	float MinAllowedDashHeight;

	/** Minimum distance from the ground a character has to be to be able to perform an air attack */
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0"))
	float MinAllowedAttackHeight;
	
	virtual void BeginPlay() override;

	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
};
