// Fill out your copyright notice in the Description page of Project Settings.


#include "Pawn/ReplicatedCameraComponent.h"

#include "Net/UnrealNetwork.h"

UReplicatedCameraComponent::UReplicatedCameraComponent()
{
	PrimaryComponentTick.bCanEverTick = true;
	PrimaryComponentTick.SetTickFunctionEnable(true);
	SetIsReplicatedByDefault(true);

	// Direct transform replication
	ControllerNetUpdateRate = 100.0f; // 100 htz is default
	ControllerNetUpdateCount = 0.0f;
}

// Naive direct transform replication (replace with input rep?)

void UReplicatedCameraComponent::UpdateState(float DeltaTime)
{
	if (GetOwner()->HasLocalNetOwner())
	{
		if (GetIsReplicated())
		{
			const FVector Loc = GetRelativeLocation();
			const FRotator Rot = GetRelativeRotation();

			if (!Loc.Equals(ReplicatedTransform.Position) || !Rot.Equals(ReplicatedTransform.Rotation))
			{
				ControllerNetUpdateCount += DeltaTime;
				if (ControllerNetUpdateCount >= (1.0f / ControllerNetUpdateRate)) // todo save inverse?
				{
					ControllerNetUpdateCount = 0.0f;

					ReplicatedTransform.Position = Loc;
					ReplicatedTransform.Rotation = Rot;
					if (GetNetMode() == NM_Client) // why do we differentiate here between netmode and authority?
					{
						ServerSendControllerTransformRpc(ReplicatedTransform);
					}
				}
			}
		}
	}
}

void UReplicatedCameraComponent::TickComponent(float DeltaTime, ELevelTick TickType,
                                               FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	UpdateState(DeltaTime);
}

void UReplicatedCameraComponent::GetLifetimeReplicatedProps(TArray<class FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	DISABLE_REPLICATED_PRIVATE_PROPERTY(USceneComponent, RelativeLocation);
	DISABLE_REPLICATED_PRIVATE_PROPERTY(USceneComponent, RelativeRotation);
	DISABLE_REPLICATED_PRIVATE_PROPERTY(USceneComponent, RelativeScale3D);

	// Skipping the owner with this as the owner will use the controllers location directly
	DOREPLIFETIME_CONDITION(UReplicatedCameraComponent, ReplicatedTransform, COND_SkipOwner);
	DOREPLIFETIME(UReplicatedCameraComponent, ControllerNetUpdateRate);
}

void UReplicatedCameraComponent::ServerSendControllerTransformRpc_Implementation(FReplicatedTransform NewTransform)
{
	// Store new transform and trigger OnRep_Function
	ReplicatedTransform = NewTransform;

	if (!GetOwner()->HasLocalNetOwner())
		OnRep_ReplicatedTransform();
}

bool UReplicatedCameraComponent::ServerSendControllerTransformRpc_Validate(FReplicatedTransform NewTransform)
{
	return true;
	// Optionally check to make sure that player is inside of their bounds and deny it if they aren't?
}