UI/Components/InspectorSheet.razor
@using Sandbox.UI;

@inherits Panel
@namespace HC3.UI

<root>
	@foreach ( var property in Properties )
	{
		if ( !property.TryGetAttribute<InspectableAttribute>( out var attrib ) )
			continue;

		var propertyType = property.PropertyType;
		if ( property.IsNullable )
		{
			if ( property.IsNull )
				continue;

			propertyType = property.NullableType;
		}

		property.TryGetAttribute<MinMaxAttribute>( out var minmaxAttrib );

		<div class="row">
			@if ( property.TryGetAttribute<IconAttribute>( out var iconAttr ) )
			{
				<i>@iconAttr.Value</i>
			}

			<label class="name">@property.DisplayName</label>

			@if ( propertyType == typeof( bool ) )
			{
				<SwitchControl Value=@(property.GetValue<bool>()) OnValueChanged=@((bool v) =>property.SetValue<bool>(v))/>
			}
			else if ( propertyType == typeof( Color ) )
			{
				<div class="color-swatch" style=@($"background-color: {property.GetValue<Color>().Hex}") onclick=@(() => PickColor(property))></div>
			}
			else if ( propertyType == typeof( Resource ) )
			{
				<DropDown Options=@(ResourceUtils.GetOptions<Resource>()) Value=@(property.GetValue<Resource>()?.ResourcePath ?? "none") ValueChanged=@((string path) => property.SetValue( ResourceLibrary.Get<Resource>( path ))) />
			}
			else if ( propertyType.IsEnum )
			{
				<DropDown Value=@(property.GetValue<object>()) BuildOptions=@(() => BuildEnumOptionsFrom( property ))/>
			}
			else
			{
				<TextEntry
					MinValue=@minmaxAttrib?.MinValue
					MaxValue=@minmaxAttrib?.MaxValue
					[email protected]
					Numeric=@(propertyType != typeof(string))
					Value=@(property.GetValue<string>())
					OnTextEdited=@((string x) => { property.SetValue<string>(x); }) />
			}
		</div>
	}
</root>

@code
{
    [Property] public IEnumerable<SerializedProperty> Properties { get; set; }

    /// <summary>
    /// Build enum options from a serialized property
    /// </summary>
    /// <param name="property"></param>
    /// <returns></returns>
    public static List<Option> BuildEnumOptionsFrom( SerializedProperty property )
    {
        var options = new List<Option>();
        var enumDesc = TypeLibrary.GetEnumDescription(property.PropertyType);

        foreach ( var x in enumDesc )
        {
            options.Add( new( x.Title, x.ObjectValue ) );
        }

        return options; 
    }

    /// <summary>Should these properties be visible?
    /// </summary>
    /// <param name="properties"></param>
    /// <returns></returns>

    public static bool ShouldShow( IEnumerable<SerializedProperty> properties )
    {
        var props = new List<SerializedProperty>();

        foreach ( var x in properties )
        {
            if ( !x.TryGetAttribute<InspectableAttribute>( out var attrib ) )
                continue;

            var propertyType = x.PropertyType;
            if ( x.IsNullable )
            {
                if ( x.IsNull )
                    continue;
            }
            props.Add( x );
        }

        return props.Count > 0;
    }

    ColorPicker _colorPicker;

    /// <summary>
    /// Open a colour picker for this property that sets the SerializedProperty value on change
    /// </summary>
    /// <param name="property"></param>
    void PickColor( SerializedProperty property )
	{
        _colorPicker?.Close();
        _colorPicker = new ColorPicker(property.GetValue<Color>(),
			color =>
			{
				property.SetValue<Color>( color );
				StateHasChanged();
			}
		);

		var window = WindowManager.Instance.Focused;
		if ( window.IsValid() )
		{
			window.OpenSubwindow( _colorPicker );
		}
	}
}