// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "WeaponSystem/BaseWeaponClass.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "Components/ArrowComponent.h"
#include "GadgetSystem/GadgetManager.h"
#include "Inventory/InventoryComponent.h"
#include "Pawn/VICharacter.h"

#include "EndlessVendettaCharacter.generated.h"

class UWeaponInventory;
class UInputComponent;
class USkeletalMeshComponent;
class USceneComponent;
class UCameraComponent;
class UAnimMontage;
class USoundBase;

UCLASS(config=Game)
class AEndlessVendettaCharacter : public ACharacter
{
	GENERATED_BODY()
	
protected:
	/** Pawn mesh: 1st person view (arms; seen only by self) */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Mesh)
	USkeletalMeshComponent* Mesh1P;
	
private:
	/** First person camera */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
	UCameraComponent* FirstPersonCameraComponent;

	/** MappingContext */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
	UInputMappingContext* DefaultMappingContext;

	/** Jump Input Action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
	UInputAction* JumpAction;

	/** Move Input Action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
	UInputAction* MoveAction;

	// Gadget Actions
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
	UInputAction* ReconAction;
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
	UInputAction* CombatAction;

	/** Weapon Equip Action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
	UInputAction* EquipPrimaryWeapon;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
	UInputAction* EquipSecondaryWeapon;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
	class UInputAction* TapShootAction;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
	class UInputAction* GunAimInAction;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Input, meta=(AllowPrivateAccess = "true"))
	class UInputAction* GunReloadAction;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	UInputAction* CrouchAction;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	UInputAction* InteractAction;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	UInputAction* SprintAction;

public:
	AEndlessVendettaCharacter();

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stats")
	float CurrentHealth = 100.0f;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Stats")
	float MaxHealth = 100.0f;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Stats")
	float DefaultHealth = 100.0f;

	//STAMINA AND SPRINT SPEED
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Stats")
	float MaxStamina  = 100;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Stats")
	float CurrentStamina;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Stats")
	float StaminaDecreaseRate = 0.2;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Stats")
	float StaminaRegenRate = 0.05;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Stats")
	float SprintSpeed = 900;

	//Getting the charMovementComp
	UCharacterMovementComponent* CharacterMovement = GetCharacterMovement();
	float WalkSpeed;
	float OriginalWalkSpeed;

	AActor* PrimaryWeaponActor;
	AActor* SecondaryWeaponActor;
	bool bIsPrimaryWeaponCreated = false;
	bool bIsSecondaryWeaponCreated = false;
	bool bIsWeaponPickedUp = false;

protected:
	virtual void BeginPlay() override;
	virtual void Tick(float DeltaTime) override;

	UPROPERTY(EditDefaultsOnly, Category = "Gadget")
	TSubclassOf<AGadgetManager> GadgetManagerClass;

	void RegenHealth();
	FTimerHandle RegenHealthTimerHandle;
	void Heal(const float Amount);

public:
	int Money = 2000;
	AGadgetManager* GadgetManager;
	bool bIsReloading = false;

	bool bIsPlayerMoving = false;

	UPROPERTY(VisibleAnywhere)
	bool bIsPlayerSprinting = false;

	double MoveGroundSpeed;

	/** Look Input Action */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	class UInputAction* LookAction;

	/** Bool for AnimBP to switch to another animation set */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Weapon)
	bool bHasRifle;

	/** Setter to set the bool */
	UFUNCTION(BlueprintCallable, Category = Weapon)
	void SetHasRifle(bool bNewHasRifle);

	/** Getter for the bool */
	UFUNCTION(BlueprintCallable, Category = Weapon)
	bool GetHasRifle();

	UPROPERTY(EditAnywhere, Category = "Weapons")
	TSubclassOf<ABaseWeaponClass> PrimaryWeaponClass;

	UPROPERTY(EditAnywhere, Category = "Weapons")
	TSubclassOf<ABaseWeaponClass> SecondaryWeaponClass;

	ABaseWeaponClass* PrimaryWeapon;
	ABaseWeaponClass* SecondaryWeapon;

	UFUNCTION(BlueprintCallable, Category = "Weapons")
	void FireCaller();

	UFUNCTION(BlueprintCallable, Category = "Weapons")
	void GunRightClick();

	UFUNCTION(BlueprintCallable, Category = "Weapons")
	void StopGunRightClick();

	UFUNCTION(BlueprintCallable, Category = "Weapons")
	void GunReload();

	UFUNCTION(BlueprintCallable, Category = "Weapons")
	void StopFire();

	void Sprint();
	void StopSprint();

	void Jumping();
	void StopJump();
	bool bHasPlayerJumped = false;

	UArrowComponent* ScopedLocationArrow;

	UPROPERTY(EditAnywhere, Category = "Dont Touch")
	bool bIsScoped;

	UFUNCTION(Exec)
	void DamagePlayer(const float Damage);

protected:
	/** Called for movement input */
	void Move(const FInputActionValue& Value);

	/** Called for looking input */
	void Look(const FInputActionValue& Value);

	void ToggleRecon();
	void ToggleCombat();

	UPROPERTY(EditDefaultsOnly, Category = "Interaction")
	float InteractionRange = 250;
	void Interact();

protected:

	// Used by vault it plugin to run vaulting animations
	USkeletalMeshComponent* FP_SkeletalMesh = nullptr;

	// APawn interface
	virtual void SetupPlayerInputComponent(UInputComponent* InputComponent) override;
	// End of APawn interface

public:
	
	
	UFUNCTION(BlueprintCallable, Category = "Stealth")
	void SetCrouch();
	UFUNCTION(BlueprintCallable, Category = "Stealth")
	void SetUnCrouch();

	/** Returns Mesh1P Sub-object **/
	USkeletalMeshComponent* GetMesh1P() const { return Mesh1P; }
	/** Returns FirstPersonCameraComponent Sub-object **/
	UCameraComponent* GetFirstPersonCameraComponent() const { return FirstPersonCameraComponent; }

	UFUNCTION(BlueprintCallable, Category = "Damage Control")
	virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;

	void WeaponPickUpSystem();

	void EquipPrimary();
	void EquipSecondary();

	void WeaponSwitcher(AActor* Outhit);

	UFUNCTION(BlueprintImplementableEvent)
	void CheckpointCompletedUI(const FString& CheckpointDesc, bool CompletedBounty = false);

	// Returns true if successfully changed to a new gadget, can fail if the target gadget to replace is being used
	bool UpdateGadgetType(TSubclassOf<AGadgetBase> NewGadgetClass);

	UInventoryComponent* InventoryComponent;
	UFUNCTION(Exec)
	void UpdateInventorySize(int Cols, int Rows);
};
