Editor/Inspector/StyleRuleWizard.cs
using Sandbox.UI;
using System.Linq;
using Button = Editor.Button;
using Label = Editor.Label;

namespace Panelize;

public class StyleRuleWizard : Window
{
	public static StyleRuleWizard OpenWithSession(Panel panel, Action onFinished = null, StyleBlock block = null )
	{
		StyleSheet sheet = PanelEditorSession.Current?.PanelSheets?.FirstOrDefault();
		if(sheet == null)
			sheet = panel.AllStyleSheets.FirstOrDefault();

		return new StyleRuleWizard( panel, sheet, onFinished, block );
	}
	public Action OnFinished;
	Panel panel;
	string rule;
	List<string> parts = new();
	LineEdit rulePreview;
	Button addButton;
	Layout editor;
	StyleSheet sheet;
	StyleBlock block;
	public StyleRuleWizard( Panel panel, StyleSheet sheet, Action onFinished = null, StyleBlock block = null )
	{
		ArgumentNullException.ThrowIfNull( panel );
		ArgumentNullException.ThrowIfNull( sheet );
		WindowTitle = "Add Rule...";

		this.panel = panel;
		this.sheet = sheet;
		this.block = block ?? new()
		{
			Styles = new()
		};
		OnFinished = onFinished;

		MinimumWidth = 720f;
		MinimumHeight = 720f;

		Canvas = new ScrollArea( this );
		Canvas.Layout = Layout.Column();
		editor = Canvas.Layout;
		editor.Margin = new( 8f );

		Rebuild();
		Show();
	}

	public void Rebuild()
	{
		editor.Clear( true );

		editor.Add( new Label.Title( "Add Style Rule" ) );

		rulePreview = new()
		{
			PlaceholderText = "Style Rule"
		};
		rulePreview.EditingFinished += UpdateRuleFromText;
		editor.Add( rulePreview );

		editor.Add(CreateSection( "Panel" ), 0);
		editor.Add( CreateElementEditor( panel ) );
		if(!string.IsNullOrEmpty(panel.Id))
		{
			editor.Add(CreateIdEditor( panel.Id ), 0);
		}

		foreach(string c in panel.Class)
		{
			editor.Add(CreateClassEditor(c), 0);
		}

		Panel parent = panel.Parent;
		while ( parent.IsValid() )
		{
			if ( parent is RootPanel ) break;

			editor.Add( CreateSection( $"Parent ({parent.ElementName})" ) );
			editor.Add( CreateElementEditor( parent ));

			if(!string.IsNullOrEmpty(parent.Id))
				editor.Add( CreateIdEditor( parent.Id) );

			foreach (var c in parent.Class)
			{
				editor.Add( CreateClassEditor( c ), 0 );
			}

			parent = parent.Parent;
		}

		editor.Add( CreateSection( "Events" ) );
		editor.Add( CreateRule( ":hover", "Hover" ), 0 );
		editor.Add( CreateRule( ":active", "Active" ), 0 );
		editor.Add( CreateRule( ":intro", "Intro" ), 0 );
		editor.Add( CreateRule( ":outro", "Outro" ), 0 );

		editor.Add( CreateSection( "Layout" ) );
		editor.Add( CreateRule( ":empty", "No Children" ) );
		editor.Add( CreateRule( ":first-child", "Is First Child" ) );
		editor.Add( CreateRule( ":last-child", "Is Last Child" ) );
		editor.Add( CreateRule( ":only-child", "Is Only Child" ) );

		addButton = new( "Add", "add" )
		{
			Enabled = false
		};
		addButton.Clicked += Finish;
		editor.AddStretchCell();
		editor.Add( addButton );

		AdjustSize();
	}

	private void Finish()
	{
		block.SetSelector( rule );
		sheet.Nodes.Add( block );
		PanelUtils.DirtyStyles(panel);

		OnFinished?.Invoke();
		Destroy();
	}

	private void UpdateRuleFromText()
	{
		rule = rulePreview.Text;
		parts = rule.Split( ' ' ).ToList();

		UpdateControls();
	}

	private void UpdateRuleFromParts()
	{
		rule = string.Join( ' ', parts );
		rulePreview.Text = rule;

		UpdateControls();
	}

	private void UpdateControls()
	{
		addButton.Enabled = parts.Count > 0;
	}

	private void AddRule( string value )
	{
		if(!parts.Contains( value ) )
		{
			parts.Add( value );
			UpdateRuleFromParts();
		}
	}

	private void RemoveRule( string value )
	{
		if(parts.Contains(value))
		{
			parts.Remove( value );
			UpdateRuleFromParts();
		}
	}

	private Widget CreateSection(string text)
	{
		Label header = new Label( text );
		header.SetStyles( "font-size: 18px; font-family: Roboto; font-weight: 600;" );
		return header;
	}
	private StyleRuleRow CreateRule(string rule, string label)
	{
		StyleRuleRow row = new( rule, label );
		row.RuleSelected += ( value ) =>
		{
			if ( value )
			{
				AddRule( rule );
			}
			else
			{
				RemoveRule( rule );
			}
		};

		return row;
	}
	private Widget CreateIdEditor(string value)
	{
		StyleRuleRow row = CreateRule( $"#{value}", $"Id {value}" );
		return row;
	}

	private Widget CreateClassEditor(string value)
	{
		string rule = $".{value}";
		StyleRuleRow row = CreateRule( rule, $"Class {value}" );
		return row;
	}

	private Widget CreateElementEditor(Panel panel)
	{
		string rule = panel.ElementName;
		StyleRuleRow row = CreateRule( rule, $"Element {rule}" );
		return row;
	}
}

public class StyleRuleRow : Widget
{
	public Action<bool> RuleSelected;
	string text;
	string rule;

	public StyleRuleRow(string value, string label) 
	{
		text = label;
		rule = value;

		Layout = Layout.Row();
		Rebuild();
	}
	protected override void OnPaint()
	{
		
	}
	public void Rebuild()
	{
		Layout.Clear( true );
		Label label = new( text )
		{
			ToolTip = rule
		};
		Layout.Add( label, 1 );

		Checkbox control = new( this );
		control.OnEdited += OnRuleSelected;
		Layout.Add( control, 0 );
	}

	private void OnRuleSelected(bool value)
	{
		RuleSelected?.Invoke( value );
	}
}