// Gravity Stomp Copyright Kevin Poretti

#pragma once

// UE includes
#include "CoreMinimal.h"
#include "GameFramework/CharacterMovementComponent.h"

#include "GSCharacterMovementComponent.generated.h"

/**
 *	Subclass of CharacterMovementComponent which allows for a custom gravity direction to be applied to the character while falling
 */
UCLASS()
class GRAVITYSTOMPGAME_API UGSCharacterMovementComponent : public UCharacterMovementComponent
{
	GENERATED_BODY()

public:
	UGSCharacterMovementComponent();

	UFUNCTION(BlueprintPure)
	FORCEINLINE FVector GetCharacterUpDirection() const { return CharacterUpDirection; }

	UFUNCTION(BlueprintCallable)
	void SetCharacterUpDirection(FVector NewUpDirection);

	UFUNCTION(BlueprintPure)
	float GetRollFromCharacterUpDir(const FVector& UpDir) const;

	UFUNCTION(BlueprintPure)
    FORCEINLINE bool IsCharacterUpAlignedToWorldUp() const;

	// UCharacterMovementComponent interface

	virtual FVector ConstrainInputAcceleration(const FVector& InputAcceleration) const override;

	virtual void OnMovementModeChanged(EMovementMode PreviousMovementMode, uint8 PreviousCustomMode) override;

	virtual void PhysicsRotation(float DeltaTime) override;

	// walking
	virtual void PhysWalking(float deltaTime, int32 Iterations) override;

	virtual void MoveAlongFloor(const FVector& InVelocity, float DeltaSeconds, FStepDownResult* OutStepDownResult) override;

	virtual FVector ComputeGroundMovementDelta(const FVector& Delta, const FHitResult& RampHit, const bool bHitFromLineTrace) const override;

	virtual void MaintainHorizontalGroundVelocity() override;

    virtual float SlideAlongSurface(const FVector& Delta, float Time, const FVector& InNormal, FHitResult& Hit, bool bHandleImpact) override;

	virtual void AdjustFloorHeight() override;

	// falling
	virtual void PhysFalling(float deltaTime, int32 Iterations) override;

	virtual FVector GetFallingLateralAcceleration(float DeltaTime) override;

	virtual void ComputeFloorDist(const FVector& CapsuleLocation, float LineDistance, float SweepDistance, FFindFloorResult& OutFloorResult, float SweepRadius, const FHitResult* DownwardSweepResult) const override;

	virtual bool IsValidLandingSpot(const FVector& CapsuleLocation, const FHitResult& Hit) const override;

	virtual bool IsWalkable(const FHitResult& Hit) const override;

	virtual bool FloorSweepTest(FHitResult& OutHit, const FVector& Start, const FVector& End, ECollisionChannel TraceChannel, const FCollisionShape& CollisionShape, const FCollisionQueryParams& Params, const FCollisionResponseParams& ResponseParam) const override;
	// End UCharacterMovementComponent interface

private:
	FVector CharacterUpDirection = FVector::UpVector;
};
