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

#include "EndlessVendettaCharacter.h"
#include "Animation/AnimInstance.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InteractionInterface.h"
#include "AI/EnemyCharacter.h"
#include "Engine/DamageEvents.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Kismet/GameplayStatics.h"
#include "GameFramework/MovementComponent.h"
#include "Inventory/InventoryComponent.h"
#include "EndlessVendettaGameMode.h"


//////////////////////////////////////////////////////////////////////////
// AEndlessVendettaCharacter

AEndlessVendettaCharacter::AEndlessVendettaCharacter()
{
	// Character doesnt have a rifle at start
	bHasRifle = false;

	//Enable Crouching
	GetCharacterMovement()->GetNavAgentPropertiesRef().bCanCrouch = true;
	// Set size for collision capsule
	GetCapsuleComponent()->InitCapsuleSize(55.f, 96.0f);

	// Create a CameraComponent	
	FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
	FirstPersonCameraComponent->SetupAttachment(GetCapsuleComponent());
	FirstPersonCameraComponent->SetRelativeLocation(FVector(-10.f, 0.f, 60.f)); // Position the camera
	FirstPersonCameraComponent->bUsePawnControlRotation = true;

	// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
	Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
	Mesh1P->SetOnlyOwnerSee(true);
	Mesh1P->SetupAttachment(FirstPersonCameraComponent);
	Mesh1P->bCastDynamicShadow = false;
	Mesh1P->CastShadow = false;
	//Mesh1P->SetRelativeRotation(FRotator(0.9f, -19.19f, 5.2f));
	Mesh1P->SetRelativeLocation(FVector(-30.f, 0.f, -150.f));
}

void AEndlessVendettaCharacter::BeginPlay()
{
	// Call the base class  
	Super::BeginPlay();

	// Set the fp skeletal mesh for the vault it plugin to use
	TArray<UActorComponent*> MeshActComps = GetComponentsByClass(USkeletalMeshComponent::StaticClass());
	for (auto MeshActorComponent : MeshActComps)
	{
		USkeletalMeshComponent* MeshSkeletalComp = Cast<USkeletalMeshComponent>(MeshActorComponent);
		if (MeshSkeletalComp->ComponentHasTag("FP_Mesh"))
		{
			FP_SkeletalMesh = MeshSkeletalComp;
			break;
		}
	}

	//Add Input Mapping Context
	if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
	{
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
		{
			Subsystem->AddMappingContext(DefaultMappingContext, 0);
		}
	}
	AActor* GadgetManagerActor = GetWorld()->SpawnActor<AActor>(GadgetManagerClass, GetActorLocation(), GetActorRotation());
	GadgetManager = Cast<AGadgetManager>(GadgetManagerActor);
	FAttachmentTransformRules AttachmentRules(EAttachmentRule::SnapToTarget, true);
	GadgetManagerActor->AttachToComponent(GetRootComponent(), AttachmentRules);
	for (UActorComponent* PlayersCamera : GetComponentsByTag(UCameraComponent::StaticClass(), FName("PlayersCamera")))
	{
		GadgetManager->SpawnGadgetsOnBeginPlay(Cast<USceneComponent>(PlayersCamera));
		break;
	}

	InventoryComponent = Cast<UInventoryComponent>(GetWorld()->GetFirstPlayerController()->GetComponentByClass(UInventoryComponent::StaticClass()));
	WalkSpeed = CharacterMovement->MaxWalkSpeed;
	OriginalWalkSpeed = CharacterMovement->MaxWalkSpeed;
	CurrentStamina = MaxStamina;
}

void AEndlessVendettaCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	WeaponPickUpSystem();
	MoveGroundSpeed = Cast<UMovementComponent>(GetComponentByClass(UMovementComponent::StaticClass()))->Velocity.Size();

	if (MoveGroundSpeed > 0)
	{
		bIsPlayerMoving = true;
	}
	else if (MoveGroundSpeed <= 0)
	{
		this->GetFirstPersonCameraComponent()->SetFieldOfView(90);
		bIsPlayerMoving = false;
	}
	if (bPressedJump)
	{
		if(CurrentStamina <= 0.0f)
		{
			CurrentStamina -= 20.0f;
		}
	}
	//PLAYER STAMINA HANDLING
	if (MoveGroundSpeed > 0)
	{
		if (bIsPlayerSprinting)
		{
			CurrentStamina -= FMath::Clamp(StaminaDecreaseRate, 0.0f, 100.0f);
			if (CurrentStamina <= 0.0f)
			{
				bIsPlayerSprinting = false;
				this->GetFirstPersonCameraComponent()->SetFieldOfView(90);
				CurrentStamina = 0.0f;
				CharacterMovement->MaxWalkSpeed = OriginalWalkSpeed;
			}
		}
	}
	if (!bIsPlayerSprinting)
	{
		if(CurrentStamina >= 100.0f)
		{
			CurrentStamina = 100.0f;
			return;
		}
		CurrentStamina += FMath::Clamp(StaminaRegenRate, 0.0f, 100.0f);
	}
}

void AEndlessVendettaCharacter::RegenHealth()
{
	Heal(10);
	if (GetWorld()->GetTimerManager().GetTimerRate(RegenHealthTimerHandle) > 1.0f)
	{
		GetWorld()->GetTimerManager().ClearTimer(RegenHealthTimerHandle);
		GetWorld()->GetTimerManager().SetTimer(RegenHealthTimerHandle, this, &AEndlessVendettaCharacter::RegenHealth, 1.0f, true);
	}
	if (CurrentHealth >= MaxHealth) GetWorld()->GetTimerManager().ClearTimer(RegenHealthTimerHandle);
}

void AEndlessVendettaCharacter::Heal(const float Amount)
{
	CurrentHealth += FMath::Clamp(Amount, 0, MaxHealth);
}

void AEndlessVendettaCharacter::WeaponPickUpSystem()
{
	FHitResult OutHit;
	FCollisionQueryParams QueryParams = FCollisionQueryParams::DefaultQueryParam;
	QueryParams.AddIgnoredActor(this);
	QueryParams.AddIgnoredActor(PrimaryWeapon);
	QueryParams.AddIgnoredActor(SecondaryWeapon);
	FVector LT_Start = FirstPersonCameraComponent->GetComponentLocation();
	FVector LT_End = LT_Start + (FirstPersonCameraComponent->GetForwardVector() * InteractionRange);
	if (!GetWorld()->LineTraceSingleByChannel(OutHit, LT_Start, LT_End, ECC_Camera, QueryParams)) return;

	AActor* HitActor = OutHit.GetActor();
	IInteractionInterface* InteractableActor = Cast<IInteractionInterface>(HitActor);
	if (InteractableActor) InteractableActor->InteractPrompt();
}

//////////////////////////////////////////////////////////////////////////// Input

void AEndlessVendettaCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	// Set up action bindings
	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
	{
		//Jumping
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
		
		//Moving
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AEndlessVendettaCharacter::Move);
		EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Started, this, &AEndlessVendettaCharacter::Sprint);
		EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &AEndlessVendettaCharacter::StopSprint);

		//Looking
		EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AEndlessVendettaCharacter::Look);

		// Gadget Toggling
		EnhancedInputComponent->BindAction(ReconAction, ETriggerEvent::Started, this, &AEndlessVendettaCharacter::ToggleRecon);
		EnhancedInputComponent->BindAction(CombatAction, ETriggerEvent::Started, this, &AEndlessVendettaCharacter::ToggleCombat);

		//Weapon Switching
		EnhancedInputComponent->BindAction(EquipPrimaryWeapon, ETriggerEvent::Triggered, this, &AEndlessVendettaCharacter::EquipPrimary);
		EnhancedInputComponent->BindAction(EquipSecondaryWeapon, ETriggerEvent::Triggered, this, &AEndlessVendettaCharacter::EquipSecondary);

		//Weapon Shooting
		EnhancedInputComponent->BindAction(TapShootAction, ETriggerEvent::Triggered, this, &AEndlessVendettaCharacter::FireCaller);
		EnhancedInputComponent->BindAction(TapShootAction, ETriggerEvent::Completed, this, &AEndlessVendettaCharacter::StopFire);
		EnhancedInputComponent->BindAction(GunAimInAction, ETriggerEvent::Triggered, this, &AEndlessVendettaCharacter::GunRightClick);
		EnhancedInputComponent->BindAction(GunAimInAction, ETriggerEvent::Completed, this, &AEndlessVendettaCharacter::StopGunRightClick);

		//Weapon Reloading
		EnhancedInputComponent->BindAction(GunReloadAction, ETriggerEvent::Triggered, this, &AEndlessVendettaCharacter::GunReload);

		//Crouching
		EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Started, this, &AEndlessVendettaCharacter::SetCrouch);
		EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Completed, this, &AEndlessVendettaCharacter::SetUnCrouch);

		//Interacting
		EnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Started, this, &AEndlessVendettaCharacter::Interact);
	}
}

void AEndlessVendettaCharacter::Interact()
{
	FHitResult OutHit;
	FCollisionQueryParams QueryParams = FCollisionQueryParams::DefaultQueryParam;
	QueryParams.AddIgnoredActor(this);
	FVector LT_Start = FirstPersonCameraComponent->GetComponentLocation();
	FVector LT_End = LT_Start + (FirstPersonCameraComponent->GetForwardVector() * InteractionRange);
	if (IsValid(PrimaryWeapon))
	{
		QueryParams.AddIgnoredActor(PrimaryWeapon);
	}
	if (IsValid(SecondaryWeapon))
	{
		QueryParams.AddIgnoredActor(SecondaryWeapon);
	}
	if (!GetWorld()->LineTraceSingleByChannel(OutHit, LT_Start, LT_End, ECC_Camera, QueryParams)) return;
	AActor* HitActor = OutHit.GetActor();
	UE_LOG(LogTemp, Warning, TEXT("Hit actor: %s"), *HitActor->GetName());
	IInteractionInterface* InteractableActor = Cast<IInteractionInterface>(HitActor);
	if (InteractableActor) InteractableActor->Interact();
}


void AEndlessVendettaCharacter::SetCrouch()
{
	Crouch();
}

void AEndlessVendettaCharacter::SetUnCrouch()
{
	UnCrouch();
}

float AEndlessVendettaCharacter::TakeDamage(const float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
	CurrentHealth -= DamageAmount;
	if (CurrentHealth <= 0)
	{
		CurrentHealth = 0;
		if (!GetWorld()->GetTimerManager().IsTimerActive(RegenHealthTimerHandle))
		{
			GetWorld()->GetTimerManager().ClearTimer(RegenHealthTimerHandle);
		}
		UE_LOG(LogTemp, Warning, TEXT("Player is dead"));

		TArray<AActor*> FoundActors;
		UGameplayStatics::GetAllActorsWithTag(GetWorld(), FName(TEXT("Respawn")), FoundActors);
		if (FoundActors.Num() > 0)
		{
			const AActor* RespawnPoint = FoundActors[0];
			SetActorLocationAndRotation(RespawnPoint->GetActorLocation(), RespawnPoint->GetActorRotation());
			CurrentHealth = MaxHealth;
			return Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
		}

		UGameplayStatics::OpenLevel(this, FName(*GetWorld()->GetName()), false);
		return Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
	}

	GetWorld()->GetTimerManager().ClearTimer(RegenHealthTimerHandle);
	GetWorld()->GetTimerManager().SetTimer(RegenHealthTimerHandle, this, &AEndlessVendettaCharacter::RegenHealth, 5.0f, true);

	return Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
}


void AEndlessVendettaCharacter::ToggleRecon()
{
	if (!GadgetManager->IsValidReconGadget()) return;

	if (IsValid(PrimaryWeapon)) EquipPrimary();
	if (IsValid(SecondaryWeapon)) EquipSecondary();

	if (GadgetManager->IsReconEquipped())
	{
		GadgetManager->TryToUnequipRecon();
		return;
	}

	if (GadgetManager->IsValidCombatGadget() && GadgetManager->IsCombatEquipped() && !GadgetManager->TryToUnequipCombat())
	{
		// Do nothing if combat is equipped and can't be unequipped at this moment
		return;
	}

	GadgetManager->EquipRecon();
}

void AEndlessVendettaCharacter::ToggleCombat()
{
	if (!GadgetManager->IsValidCombatGadget()) return;

	if (IsValid(PrimaryWeapon)) EquipPrimary();
	if (IsValid(SecondaryWeapon)) EquipSecondary();

	if (GadgetManager->IsCombatEquipped())
	{
		GadgetManager->TryToUnequipCombat();
		return;
	}

	if (GadgetManager->IsValidReconGadget() && GadgetManager->IsReconEquipped() && !GadgetManager->TryToUnequipRecon())
	{
		// Do nothing if recon is equipped and can't be unequipped at the moment
		return;
	}

	GadgetManager->EquipCombat();
}


//When 1 is pressed it calls EquipPrimary
void AEndlessVendettaCharacter::EquipPrimary()
{
	FActorSpawnParameters spawnParams;
	spawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
	FAttachmentTransformRules AttachmentRules(EAttachmentRule::SnapToTarget, true);
	FDetachmentTransformRules DetatchRules(EDetachmentRule::KeepWorld, false);
	if (bIsReloading) return;
	if (IsValid(PrimaryWeapon))
	{
		PrimaryWeapon->DetachFromActor(DetatchRules);
		PrimaryWeapon->SetActorLocation(FVector(0,0,0), false, nullptr, ETeleportType::None);
		PrimaryWeapon->SetActorHiddenInGame(true);
		this->GetFirstPersonCameraComponent()->SetFieldOfView(90);
		UE_LOG(LogTemp, Warning, TEXT("Primary Weapon Is Hidden: %hhd"), PrimaryWeapon->IsHidden());
		PrimaryWeapon = nullptr;
		bHasRifle = false;
		GLog->Log("Primary Weapon Put Away");
		Cast<AEndlessVendettaGameMode>(GetWorld()->GetAuthGameMode())->SendEvent("DeEquip", "Pri");
		return;
	}
	if(bIsWeaponPickedUp)
	{
		PrimaryWeaponActor = GetWorld()->SpawnActor<AActor>(PrimaryWeaponClass, spawnParams);
		bIsWeaponPickedUp = false;
	}

	if (IsValid(SecondaryWeapon)) EquipSecondary();

	if (GadgetManager->IsValidReconGadget() && GadgetManager->IsReconEquipped() && !GadgetManager->TryToUnequipRecon()) return;
	if (GadgetManager->IsValidCombatGadget() && GadgetManager->IsCombatEquipped() && !GadgetManager->TryToUnequipCombat()) return;

	bHasRifle = true;
	// if(!bIsPrimaryWeaponCreated)
	// {
	// 	//Creating a new actor object called PrimaryWeapon that is based off primaryweaponClass
	// 	//Changing PrimaryWeaponActor to ABaseWeaponClass type instead of actor and storing it into PrimaryWeapon which is a ABaseClass Object
	// 	//We do this because we need to check if PrimaryWeapon is equipped and we want primaryweapon to be ABaseWeapon type and not a generic AActor
	// 	PrimaryWeaponActor = GetWorld()->SpawnActor<AActor>(PrimaryWeaponClass, spawnParams);
	// 	PrimaryWeaponActor->AttachToComponent(Mesh1P, AttachmentRules, FName("GripPoint"));
	// 	PrimaryWeapon = Cast<ABaseWeaponClass>(PrimaryWeaponActor);
	// 	PrimaryWeapon->SetActorHiddenInGame(false);
	// 	bIsPrimaryWeaponCreated = true;
	// }
	if (!IsValid(PrimaryWeaponActor)) return;
	Cast<AEndlessVendettaGameMode>(GetWorld()->GetAuthGameMode())->SendEvent("Equip", "Pri");
	PrimaryWeaponActor->AttachToComponent(Mesh1P, AttachmentRules, FName("GripPoint"));
	PrimaryWeapon = Cast<ABaseWeaponClass>(PrimaryWeaponActor);
	PrimaryWeapon->SetActorHiddenInGame(false);
	GetWorldTimerManager().ClearTimer(PrimaryWeapon->reloadTimerHandle);
}

void AEndlessVendettaCharacter::EquipSecondary()
{
	FActorSpawnParameters spawnParams;
	spawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
	FAttachmentTransformRules AttachmentRules(EAttachmentRule::SnapToTarget, true);
	FDetachmentTransformRules DetatchRules(EDetachmentRule::KeepWorld, false);
	
	if (bIsReloading) return;
	if (IsValid(SecondaryWeapon))
	{
		SecondaryWeapon->DetachFromActor(DetatchRules);
		SecondaryWeapon->SetActorLocation(FVector(0,0,0), false, nullptr, ETeleportType::None);
		SecondaryWeapon->SetActorHiddenInGame(true);
		this->GetFirstPersonCameraComponent()->SetFieldOfView(90);
		UE_LOG(LogTemp, Warning, TEXT("Secondary Weapon Is Hidden: %hhd"), SecondaryWeapon->IsHidden());
		SecondaryWeapon = nullptr;
		bHasRifle = false;
		GLog->Log("Secondary Weapon Put Away");
		return;
	}
	
	if(bIsWeaponPickedUp)
	{
		PrimaryWeaponActor = GetWorld()->SpawnActor<AActor>(PrimaryWeaponClass, spawnParams);
		bIsWeaponPickedUp = false;
	}

	if (IsValid(PrimaryWeapon)) EquipPrimary();

	if (GadgetManager->IsValidReconGadget() && GadgetManager->IsReconEquipped() && !GadgetManager->TryToUnequipRecon()) return;
	if (GadgetManager->IsValidCombatGadget() && GadgetManager->IsCombatEquipped() && !GadgetManager->TryToUnequipCombat()) return;
	
	if(!IsValid(SecondaryWeapon))
	{
		bHasRifle = true;
		if(!bIsSecondaryWeaponCreated)
		{
			SecondaryWeaponActor = GetWorld()->SpawnActor<AActor>(SecondaryWeaponClass, spawnParams);
			SecondaryWeaponActor->AttachToComponent(Mesh1P, AttachmentRules, FName("GripPoint"));
			SecondaryWeapon = Cast<ABaseWeaponClass>(SecondaryWeaponActor);
			SecondaryWeapon->SetActorHiddenInGame(false);
			bIsSecondaryWeaponCreated = true;
		}
		//UE_LOG(LogTemp, Warning, TEXT("Secondary Weapon Is Hidden: %hhd"), SecondaryWeapon->IsHidden());
		GLog->Log("Secondary Weapon Equipped");
	}
	SecondaryWeaponActor->AttachToComponent(Mesh1P, AttachmentRules, FName("GripPoint"));
	SecondaryWeapon = Cast<ABaseWeaponClass>(SecondaryWeaponActor);
	SecondaryWeapon->SetActorHiddenInGame(false);
	GetWorldTimerManager().ClearTimer(SecondaryWeapon->reloadTimerHandle);
}

void AEndlessVendettaCharacter::WeaponSwitcher(AActor* Outhit)
{
	if(Outhit->ActorHasTag("PrimaryWeapon"))
	{
		if (IsValid(PrimaryWeapon))
		{
			EquipPrimary();
		}
		bIsWeaponPickedUp = true;
		PrimaryWeaponClass = Outhit->GetClass();
		Outhit->Destroy();
		EquipPrimary();
	}
	if(Outhit->ActorHasTag("SecondaryWeapon"))
	{
		if (IsValid(SecondaryWeapon))
		{
			EquipSecondary();
		}
		bIsWeaponPickedUp = true;
		SecondaryWeaponClass = Outhit->GetClass();
		Outhit->Destroy();
		EquipSecondary();
	}
}

//Calls the fire function in the baseWeaponClass
void AEndlessVendettaCharacter::FireCaller()
{
	if (IsValid(PrimaryWeapon) && !bIsReloading)
	{
		PrimaryWeapon->Fire();
	}
	if (IsValid(SecondaryWeapon) && !bIsReloading)
	{
		SecondaryWeapon->Fire();
	}
}

void AEndlessVendettaCharacter::StopFire()
{
	if (IsValid(PrimaryWeapon))
	{
		PrimaryWeapon->CancelFire();
	}
	if (IsValid(SecondaryWeapon))
	{
		SecondaryWeapon->CancelFire();
	}
}

void AEndlessVendettaCharacter::GunRightClick()
{
	if (IsValid(PrimaryWeapon) && !bIsScoped)
	{
		for (UActorComponent* actorComp : this->GetComponentsByTag(UArrowComponent::StaticClass(), FName("ScopedLocationArrow")))
		{
			ScopedLocationArrow = Cast<UArrowComponent>(actorComp);
			break;
		}
		if (!IsValid(ScopedLocationArrow)) return;
		PrimaryWeapon->SetActorLocation(ScopedLocationArrow->GetComponentLocation());
		bIsScoped = true;
		PrimaryWeapon->WeaponScopedFire();
		this->GetFirstPersonCameraComponent()->SetFieldOfView(50); //change this number to a number you can change in editor eventually
	}
	if (IsValid(SecondaryWeapon) && !bIsScoped)
	{
		for (UActorComponent* actorComp : this->GetComponentsByTag(UArrowComponent::StaticClass(), FName("ScopedLocationArrow")))
		{
			ScopedLocationArrow = Cast<UArrowComponent>(actorComp);
			break;
		}
		if (!IsValid(ScopedLocationArrow)) return;
		bIsScoped = true;
		SecondaryWeapon->WeaponScopedFire();
		SecondaryWeapon->SetActorLocation(ScopedLocationArrow->GetComponentLocation());
		this->GetFirstPersonCameraComponent()->SetFieldOfView(50); //change this number to a number you can change in editor eventually
	}
}

void AEndlessVendettaCharacter::StopGunRightClick()
{
	if (IsValid(PrimaryWeapon))
	{
		bIsScoped = false;
		PrimaryWeapon->WeaponScopedFire();
		PrimaryWeapon->SetActorRelativeLocation(FVector(0, 0, 0));
		this->GetFirstPersonCameraComponent()->SetFieldOfView(90);
	}
	if (IsValid(SecondaryWeapon))
	{
		bIsScoped = false;
		SecondaryWeapon->WeaponScopedFire();
		SecondaryWeapon->SetActorRelativeLocation(FVector(0, 0, 0));
		this->GetFirstPersonCameraComponent()->SetFieldOfView(90);
	}
}

void AEndlessVendettaCharacter::GunReload()
{
	if (IsValid(PrimaryWeapon))
	{
		PrimaryWeapon->ReloadTimer();
		bIsReloading = true;
	}
	if (IsValid(SecondaryWeapon))
	{
		SecondaryWeapon->ReloadTimer();
		bIsReloading = true;
	}
}


void AEndlessVendettaCharacter::DamagePlayer(const float Damage)
{
	TakeDamage(Damage, FDamageEvent(), nullptr, nullptr);
}

void AEndlessVendettaCharacter::Move(const FInputActionValue& Value)
{
	// input is a Vector2D
	FVector2D MovementVector = Value.Get<FVector2D>();

	if (Controller != nullptr)
	{
		// add movement 
		AddMovementInput(GetActorForwardVector(), MovementVector.Y);
		AddMovementInput(GetActorRightVector(), MovementVector.X);
	}
}

void AEndlessVendettaCharacter::Sprint()
{
	bIsPlayerSprinting = true;
	if (bIsPlayerSprinting)
	{
		if (MoveGroundSpeed > 0)
		{
			CharacterMovement->MaxWalkSpeed = SprintSpeed;
			this->GetFirstPersonCameraComponent()->SetFieldOfView(100);
		}
	}
}

void AEndlessVendettaCharacter::StopSprint()
{
	bIsPlayerSprinting = false;
	if (!bIsPlayerSprinting)
	{
		UE_LOG(LogTemp, Display, TEXT("Player stopped sprinting"));
		CharacterMovement->MaxWalkSpeed = OriginalWalkSpeed;
		this->GetFirstPersonCameraComponent()->SetFieldOfView(90);
	}
}

void AEndlessVendettaCharacter::Jumping()
{
	if (CurrentStamina > 10.0f)
	{
		bHasPlayerJumped = true;
		if (bHasPlayerJumped)
		{
			Super::Jump();
			if (!CharacterMovement->IsFalling())
			{
				CurrentStamina -= 10.0f;
			}
			bHasPlayerJumped = false;
		}
	}
}

void AEndlessVendettaCharacter::StopJump()
{
	Super::StopJumping();
	UE_LOG(LogTemp, Display, TEXT("Player has stopped jumping"));
	bHasPlayerJumped = false;
}

void AEndlessVendettaCharacter::Look(const FInputActionValue& Value)
{
	// input is a Vector2D
	FVector2D LookAxisVector = Value.Get<FVector2D>();

	if (Controller != nullptr)
	{
		// add yaw and pitch input to controller
		AddControllerYawInput(LookAxisVector.X);
		AddControllerPitchInput(LookAxisVector.Y);
	}
}


void AEndlessVendettaCharacter::SetHasRifle(bool bNewHasRifle)
{
	bHasRifle = bNewHasRifle;
}

bool AEndlessVendettaCharacter::GetHasRifle()
{
	return bHasRifle;
}

bool AEndlessVendettaCharacter::UpdateGadgetType(TSubclassOf<AGadgetBase> NewGadgetClass)
{
	if (NewGadgetClass.GetDefaultObject()->IsA(AReconGadget::StaticClass()) && GadgetManager->ReconCantBeSwitchedOut()) return false;
	if (NewGadgetClass.GetDefaultObject()->IsA(ACombatGadget::StaticClass()) && GadgetManager->CombatCantBeSwitchedOut()) return false;

	for (UActorComponent* PlayersCamera : GetComponentsByTag(UCameraComponent::StaticClass(), FName("PlayersCamera")))
	{
		GadgetManager->SpawnGadget(NewGadgetClass, Cast<UCameraComponent>(PlayersCamera));
		break;
	}
	return true;
}

void AEndlessVendettaCharacter::UpdateInventorySize(int Cols, int Rows)
{
	UInventoryComponent* Inventory = Cast<UInventoryComponent>(GetComponentByClass(UInventoryComponent::StaticClass()));
	if (IsValid(Inventory))
	{
		Inventory->UpdateInventorySize(Cols, Rows);
	}
	else 
	{
		UE_LOG(LogTemp, Warning, TEXT("No Vaild Inventory"));
	}
}