using Sandbox;
using System.Collections.Generic;

namespace VeloX;


public partial class VeloXWheel
{

	[ConCmd( "clear_skids" )]
	public static void ClearSkids()
	{
		while ( SkidMarks.Count > 1 )
			SkidMarks.Dequeue()?.DestroyGameObject();
	}

	[ConVar( "skidmark_max_skid" )]
	public static float MaxSkid { get; set; } = 50.0f;

	[ConVar( "skidmark_min_slide" )]
	public static float MinSlide { get; set; } = 0.1f;


	private static readonly Queue<LineRenderer> SkidMarks = [];

	private LineRenderer _skidMark;

	private void ResetSkid()
	{
		_skidMark = null;
	}

	private void CreateSkid()
	{
		GameObject go = new()
		{
			WorldPosition = ContactPosition + Vehicle.WorldRotation.Down * (Radius.MeterToInch() - 0.01f),
			WorldRotation = Rotation.LookAt( hitSidewaysDirection )
		};
		_skidMark = go.AddComponent<LineRenderer>();
		_skidMark.Face = SceneLineObject.FaceMode.Normal;
		_skidMark.Points = [go];
		_skidMark.Color = Color.Black.WithAlpha( 0.5f );
		_skidMark.Opaque = false;
		_skidMark.CastShadows = false;
		_skidMark.Width = Width.MeterToInch() / 2;
		_skidMark.AutoCalculateNormals = false;
		_skidMark.SplineInterpolation = 4;
		go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true );
		go.Flags = go.Flags.WithFlag( GameObjectFlags.NotNetworked, true );
		SkidMarks.Enqueue( _skidMark );
	}

	protected void UpdateSkid()
	{
		if ( IsProxy )
			return;
		while ( SkidMarks.Count > MaxSkid )
		{
			SkidMarks.Dequeue()?.DestroyGameObject();
		}

		if ( !IsOnGround )
		{
			ResetSkid();
			return;
		}

		var slideAmount = NormalizedSlip;

		if ( slideAmount < MinSlide * 2 )
		{
			ResetSkid();
			return;
		}

		if ( !_skidMark.IsValid() )
		{
			CreateSkid();
		}
		GameObject go = new()
		{
			Parent = _skidMark.GameObject,
			WorldPosition = ContactPosition + Vehicle.WorldRotation.Down * Radius.MeterToInch(),
			WorldRotation = Rotation.LookAt( ContactNormal.RotateAround( Vector3.Zero, Rotation.FromRoll( 90 ) ) )
		};
		go.Flags = go.Flags.WithFlag( GameObjectFlags.Hidden, true );
		go.Flags = go.Flags.WithFlag( GameObjectFlags.NotNetworked, true );
		_skidMark.Points.Add( go );
	}
}
