// Project Sword & Gun Copyright © 2021 Kevin Poretti

#pragma once

#include "CoreMinimal.h"

#include "Components/SNGHealthComponent.h"
#include "Components/SNGStateMachineComponent.h"
#include "GameFramework/Character.h"
#include "Interfaces/SNGEventProcessorInterface.h"
#include "Interfaces/SNGWeaponUserInterface.h"

#include "SNGCharacterBase.generated.h"

UCLASS()
class SWORDNGUN_API ASNGCharacterBase : public ACharacter, public ISNGEventProcessorInterface, public ISNGWeaponUserInterface
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	ASNGCharacterBase();

	UFUNCTION(BlueprintCallable)
	void SetupRotateTowardsTarget(FRotator TargetRotation, float DegreesPerSecond, float MaxRotation);

	UFUNCTION(BlueprintCallable)
	void RotateTowardsTarget(float DeltaTime);
	
	UFUNCTION(BlueprintCallable)
	void SetIgnoreMovementInput(bool IsIgnored);

	UFUNCTION(BlueprintCallable)
	void SetCanCancel(bool CanCancel);
	
	UFUNCTION(BlueprintGetter)
	bool CanCancel();

	// event processing 
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	void PushEvent(FSNGEvent Event);
	
	/**
	* 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
	* characters that will want to push events to another character will have a reference
	* to the character itself rather than the state machine component
	*/ 
	virtual void PushEvent_Implementation(FSNGEvent Event);

	// weapons
	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	ASNGWeaponBase* GetCurrentWeapon();

	virtual ASNGWeaponBase* GetCurrentWeapon_Implementation();

	// damage and related 
	UFUNCTION(BlueprintCallable)
	void ApplyHitStop(float HitStopTime, float HitSlowTime);
	
	virtual void ReceiveHit(FSNGHitData const& HitData, AController* EventInstigator, AActor* DamageCauser);
	
	virtual float TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;
	
protected:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
	USNGStateMachineComponent* StateMachineComponent;
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
	USNGHealthComponent* HealthComponent;
	
	UPROPERTY(BlueprintReadOnly)
	bool bCanCancel;

	bool bIsInHitStop;
	float CurrHitStopTime;
	float CurrHitSlowTime;

	FRotator InitialRot;
	FRotator TargetRot;
	float DegPerSecond;
	float MaxRot;
	float RotateTime;
	float RotateTimeElapsed;
	
	virtual void Tick(float DeltaSeconds) override;
};
