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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "InputActionValue.h"
#include "CM_PlayerState.h"
#include "CorruptedMemoryGameMode.h"
#include "CorruptedMemoryCharacter.generated.h"

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

UCLASS(config=Game)
class ACorruptedMemoryCharacter : public ACharacter
{
	GENERATED_BODY()
	
	DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnGameStart);

	DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnGameEnd);

	UPROPERTY(BlueprintAssignable, Category = "Game")
	FOnGameStart OnGameStart;
	UPROPERTY(BlueprintAssignable, Category = "Game")
	FOnGameEnd OnGameEnd;

	/** First person camera */
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
	UCameraComponent* FirstPersonCameraComponent;

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

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

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

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

public:
	ACorruptedMemoryCharacter();

protected:
	virtual void BeginPlay();

public:
	/** 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();

	UFUNCTION(Server, Reliable)
	void ServerPlayerJoin(const FString& PlayerName, const int32& PlayerIndex, const FUniqueNetIdRepl& UNetID);
	UFUNCTION(Server, Reliable)
	void ServerSuccessfulScan(const FString& Username);


	UFUNCTION(Client, Reliable)
	void LogServerMessage(const FString& Message);

	UFUNCTION(Client, Reliable)
	void Client_EnableUserInput();
	UFUNCTION(Client, Reliable)
	void Client_DisableUserInput();

	UFUNCTION(Client, Reliable)
	void Client_GameStart();
	UFUNCTION(Client, Reliable)
	void Client_GameEnd();

	UPROPERTY(BlueprintReadOnly)
	float ScanPercentage = 0.f;

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

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

	void ScanStart(const FInputActionValue& Value);
	void ScanCancel(const FInputActionValue& Value);

protected:
	// APawn interface
	virtual void SetupPlayerInputComponent(UInputComponent* InputComponent) override;
	// End of APawn interface
	UPROPERTY()
	FTimerHandle ScanTimerHandle;

public:
	UCameraComponent* GetFirstPersonCameraComponent() const { return FirstPersonCameraComponent; }
	virtual void Tick(float DeltaSeconds) override;
	UPROPERTY(EditDefaultsOnly)
	float ScanTime = 3.f;
};


inline void ACorruptedMemoryCharacter::ServerSuccessfulScan_Implementation(const FString& Username)
{
	if (const ACorruptedMemoryGameMode* GameMode = Cast<ACorruptedMemoryGameMode>(GetWorld()->GetAuthGameMode()))
	{
		GameMode->SuccessfulScan(Username);
	}
}
