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

#pragma once

#include "CoreMinimal.h"
#include "Crowds/VelocityPostProcessorComponent.h"
#include "Math/RandomStream.h"

#include "Predictive.generated.h"

/**
 *
 */
UCLASS()
class CHARACTERPLUGIN_API UPredictive : public UVelocityPostProcessorComponent
{
	GENERATED_BODY()

public:
	UPredictive();
	
	virtual void PostProcessVelocity(float LastDeltaTime, FVector& Velocity) override;

	// These following values come directly from the Karamouzas paper (see cpp)
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float ORIENT_WEIGHT = 0.8f;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float COS_FOV_ANGLE = FMath::Cos(FMath::DegreesToRadians(100.f));  // 100 degrees (200 total)
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float REACTION_TIME = 0.4f;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float WALL_STEEPNESS = 2.f;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float WALL_DISTANCE = 0.4f;  
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		int COLLIDING_COUNT = 5;    // K most dangerous neighbors considered
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float D_MIN = 1.f;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float D_MID = 8.f;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float D_MAX = 10.f;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float AGENT_FORCE = 3.f;  // how many Newtons?
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float RADIUS = 0.45f;  // m
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float MAX_ACCELERATION = 200.f;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float PERSONAL_SPACE = 1.f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VelocityPostProcessor")
		float ANTICIPATION_TIME = 3.f;

private:
	float RayCircleTTC(const FVector2D& Dir, const FVector2D& Center, float Radius);

	FRandomStream RandomStream;
};