UI/Player/InteractionUI.razor
@using Sandbox
@using Sandbox.UI

@namespace Opium
@inherits PanelComponent

<root>
	@if (currentInteractable is not null)
	{
		<div class="box" @ref="Box">
			<div class="top left" />
			<div class="top right" />
			<div class="bottom left" />
			<div class="bottom right" />

            @if (currentInteractable.CanUse(Player.GameObject))
            {
                <div class="box-inside">
                    <InputHint @Action="Use" class="@(ShowInputHint ? "visible" : "")" />
                </div>

                @if (currentInteractable.GetUseIcon() is not null)
                {
                    <img class="icon @(ShowInteractionIcon ? "visible" : "")" [email protected]() />
                }
            }
            else
            {
                <div class="box-inside">
                    @if (currentInteractable.GetUseIcon() is not null)
                    {
                        <img class="icon @(ShowInteractionIcon ? "visible" : "")" [email protected]() />
                    }
                </div>
            }
		</div>
	}
</root>

@code
{
    /// <summary>
    /// The player
    /// </summary>
    public Opium.PlayerController Player => Components.Get<Opium.PlayerController>(FindMode.EverythingInSelfAndAncestors);

    /// <summary>
    /// poop sock
    /// </summary>
    public InteractUse Interaction => Components.Get<InteractUse>(FindMode.EverythingInSelfAndAncestors);

    public GameObject Source => ( currentInteractable?.Source.IsValid() ?? false ) ? Source : null;

    public WeaponPickup WeaponPickup => currentInteractable as WeaponPickup;

    string IsBlockActive(int blockId)
    {
        var durability = WeaponPickup?.Durability ?? 0;
        var block = durability / 33f;

        block = block.CeilToInt();
        if ( blockId < block ) return "active";

        return "";
    }

    private IInteractable currentInteractable;

    bool IsInventoryFull => !Player.Inventory.CanInsertWeapon();

    public bool ShowInteractionIcon => !string.IsNullOrEmpty(currentInteractable.GetUseIcon()) && Interaction.LookingAtObject is not null;
    public bool ShowInputHint => Interaction.LookingAtObject is not null;

    public BBox BoundingBox
    {
        get
        {
            var obj = currentInteractable;
            if (!obj.IsValid()) return default;

            var gameObject = Source.IsValid() ? Source : obj.GameObject;

            var collider = gameObject.Components.Get<Collider>(FindMode.EverythingInSelfAndDescendants);
            if (collider is not null && collider.KeyframeBody is not null)
            {
                return collider.KeyframeBody.GetBounds();
            }

            var rb = gameObject.Components.Get<Rigidbody>(FindMode.EverythingInSelfAndDescendants);
            if (rb is not null && rb.PhysicsBody is not null)
            {
                return rb.PhysicsBody.GetBounds();
            }

            return BBox.FromPositionAndSize( 0f, 32f );
        }
    }

    public Panel Box { get; set; }

    protected override void OnUpdate()
    {
        var lookObject = Interaction.LookingAtObject;
        bool shouldShow = lookObject?.ShowInteractionUI ?? false;

        if ( lookObject.IsValid() )
        {
            currentInteractable = lookObject;
        }

        GameObject gameObject = null;

        if ( currentInteractable.IsValid() )
        {
            if (currentInteractable.Source.IsValid()) gameObject = currentInteractable.Source;
            else if (!currentInteractable.Source.IsValid()) gameObject = currentInteractable.GameObject;
        }

        var bounds = BoundingBox;

		if ( gameObject.IsValid() && Box is not null )
		{
            var screenPos = Scene.Camera.PointToScreenNormal(bounds.Center);

			Box.Style.Left = Length.Fraction( screenPos.x );
			Box.Style.Top = Length.Fraction( screenPos.y );

			Box.Style.Width = 50;
			Box.Style.Height = 50;
		}

		Box?.SetClass( "visible", lookObject is not null );
	}

	protected override int BuildHash()
	{
		return HashCode.Combine( Time.Now );
	}
}