Editor/Widgets/SuiInventoryGridWizard.cs
using System;
using Editor;
using Sandbox;
using SboxUiDesigner.Runtime;

namespace SboxUiDesigner.EditorUi.Widgets;

/// <summary>
/// Modal wizard for creating an InventoryGrid (mockup Image 5). Asks for
/// grid dimensions + slot size + gap + anchor + slot style, shows a mini
/// preview, and on accept builds the grid + populates with empty slots.
/// </summary>
public sealed class SuiInventoryGridWizard : Window
{
	public Action<InventoryGridConfig> OnCreate;

	private int _columns = 8;
	private int _rows = 4;
	private float _slotSize = 64;
	private float _gap = 8;
	private SuiAnchor _anchor = SuiAnchor.MiddleCenter;

	private LineEdit _colsEdit, _rowsEdit, _sizeEdit, _gapEdit;
	private SuiAnchorPicker _anchorPicker;
	private Widget _preview;
	private Label _sizeLabel, _totalLabel;

	public SuiInventoryGridWizard()
	{
		Title = "Create Inventory Grid";
		WindowTitle = "Create Inventory Grid";
		Size = new Vector2( 540, 420 );
		MinimumSize = new Vector2( 540, 420 );
		SetWindowIcon( "grid_view" );
		DeleteOnClose = true;

		Canvas = new Widget( null );
		Canvas.Layout = Layout.Column();
		Canvas.Layout.Margin = 12;
		Canvas.Layout.Spacing = 8;

		BuildLayout();
		Show();
	}

	private void BuildLayout()
	{
		var twoCol = new Widget( Canvas );
		twoCol.Layout = Layout.Row();
		twoCol.Layout.Spacing = 16;

		// Left: settings.
		var settings = new Widget( twoCol );
		settings.Layout = Layout.Column();
		settings.Layout.Spacing = 6;

		var settingsHeader = new Label( "Grid Settings", settings );
		settingsHeader.SetStyles( "color: #9ca3af; font-size: 11px; font-weight: 600; letter-spacing: 1px;" );
		settings.Layout.Add( settingsHeader );

		_colsEdit = AddIntField( settings, "Columns", _columns, v => { _columns = v; RefreshPreview(); } );
		_rowsEdit = AddIntField( settings, "Rows", _rows, v => { _rows = v; RefreshPreview(); } );
		_sizeEdit = AddFloatField( settings, "Slot Size (px)", _slotSize, v => { _slotSize = v; RefreshPreview(); } );
		_gapEdit = AddFloatField( settings, "Gap (px)", _gap, v => { _gap = v; RefreshPreview(); } );

		var anchorRow = new Widget( settings );
		anchorRow.Layout = Layout.Row();
		anchorRow.Layout.Spacing = 8;
		var anchorLbl = new Label( "Anchor", anchorRow );
		anchorLbl.FixedWidth = 96;
		anchorLbl.SetStyles( "color: #9ca3af; font-size: 11px;" );
		anchorRow.Layout.Add( anchorLbl );
		_anchorPicker = new SuiAnchorPicker( anchorRow );
		_anchorPicker.SetCurrent( _anchor );
		_anchorPicker.AnchorSelected = a => { _anchor = a; };
		anchorRow.Layout.Add( _anchorPicker );
		anchorRow.Layout.AddStretchCell();
		settings.Layout.Add( anchorRow );

		twoCol.Layout.Add( settings, 1 );

		// Right: preview.
		var previewCol = new Widget( twoCol );
		previewCol.Layout = Layout.Column();
		previewCol.Layout.Spacing = 6;

		var previewHeader = new Label( "Preview", previewCol );
		previewHeader.SetStyles( "color: #9ca3af; font-size: 11px; font-weight: 600; letter-spacing: 1px;" );
		previewCol.Layout.Add( previewHeader );

		_preview = new GridPreview( previewCol, this );
		_preview.MinimumSize = new Vector2( 240, 180 );
		previewCol.Layout.Add( _preview, 1 );

		_sizeLabel = new Label( "", previewCol );
		_sizeLabel.SetStyles( "color: #d1d5db; font-size: 11px;" );
		previewCol.Layout.Add( _sizeLabel );

		_totalLabel = new Label( "", previewCol );
		_totalLabel.SetStyles( "color: #d1d5db; font-size: 11px;" );
		previewCol.Layout.Add( _totalLabel );

		twoCol.Layout.Add( previewCol, 1 );

		Canvas.Layout.Add( twoCol, 1 );

		// Footer buttons.
		var footer = new Widget( Canvas );
		footer.Layout = Layout.Row();
		footer.Layout.Spacing = 8;
		footer.FixedHeight = 32;
		footer.Layout.AddStretchCell();
		var cancelBtn = new Button( "Cancel", "close", footer );
		cancelBtn.Clicked += Close;
		footer.Layout.Add( cancelBtn );
		var createBtn = new Button( "Create Grid", "check", footer );
		createBtn.SetStyles( "background-color: #2563eb; color: white;" );
		createBtn.Clicked += () =>
		{
			OnCreate?.Invoke( new InventoryGridConfig
			{
				Columns = _columns,
				Rows = _rows,
				SlotSize = _slotSize,
				Gap = _gap,
				Anchor = _anchor,
			} );
			Close();
		};
		footer.Layout.Add( createBtn );
		Canvas.Layout.Add( footer );

		RefreshPreview();
	}

	private LineEdit AddIntField( Widget parent, string label, int initial, Action<int> onChange )
	{
		var row = new Widget( parent );
		row.Layout = Layout.Row();
		row.Layout.Spacing = 6;
		var lbl = new Label( label, row );
		lbl.FixedWidth = 96;
		lbl.SetStyles( "color: #9ca3af; font-size: 11px;" );
		row.Layout.Add( lbl );
		var le = new LineEdit( row );
		le.Text = initial.ToString();
		le.MaximumWidth = 100;
		le.EditingFinished += () =>
		{
			if ( int.TryParse( le.Text, out var v ) ) onChange( Math.Max( 1, v ) );
		};
		row.Layout.Add( le, 1 );
		parent.Layout.Add( row );
		return le;
	}

	private LineEdit AddFloatField( Widget parent, string label, float initial, Action<float> onChange )
	{
		var row = new Widget( parent );
		row.Layout = Layout.Row();
		row.Layout.Spacing = 6;
		var lbl = new Label( label, row );
		lbl.FixedWidth = 96;
		lbl.SetStyles( "color: #9ca3af; font-size: 11px;" );
		row.Layout.Add( lbl );
		var le = new LineEdit( row );
		le.Text = initial.ToString();
		le.MaximumWidth = 100;
		le.EditingFinished += () =>
		{
			if ( float.TryParse( le.Text, out var v ) ) onChange( MathF.Max( 1, v ) );
		};
		row.Layout.Add( le, 1 );
		parent.Layout.Add( row );
		return le;
	}

	private void RefreshPreview()
	{
		var w = _columns * _slotSize + (_columns - 1) * _gap;
		var h = _rows * _slotSize + (_rows - 1) * _gap;
		if ( _sizeLabel != null ) _sizeLabel.Text = $"Grid Size: {(int)w} × {(int)h}";
		if ( _totalLabel != null ) _totalLabel.Text = $"Total Slots: {_columns * _rows}";
		_preview?.Update();
	}

	public sealed class InventoryGridConfig
	{
		public int Columns;
		public int Rows;
		public float SlotSize;
		public float Gap;
		public SuiAnchor Anchor;
	}

	private sealed class GridPreview : Widget
	{
		private readonly SuiInventoryGridWizard _wizard;
		public GridPreview( Widget parent, SuiInventoryGridWizard wizard ) : base( parent )
		{
			_wizard = wizard;
		}

		protected override void OnPaint()
		{
			Paint.SetBrush( new Color( 0.10f, 0.10f, 0.12f ) );
			Paint.SetPen( new Color( 0.30f, 0.30f, 0.35f ), 1 );
			Paint.DrawRect( LocalRect, 4 );

			var cols = _wizard._columns;
			var rows = _wizard._rows;
			if ( cols <= 0 || rows <= 0 ) return;

			// Fit grid into available area with uniform scale.
			var availW = LocalRect.Width - 16;
			var availH = LocalRect.Height - 16;
			var slotW = (availW - (cols - 1) * 2) / cols;
			var slotH = (availH - (rows - 1) * 2) / rows;
			var slot = MathF.Min( slotW, slotH );
			var totalW = cols * slot + (cols - 1) * 2;
			var totalH = rows * slot + (rows - 1) * 2;
			var ox = LocalRect.Left + (LocalRect.Width - totalW) * 0.5f;
			var oy = LocalRect.Top + (LocalRect.Height - totalH) * 0.5f;

			Paint.SetPen( new Color( 0.55f, 0.55f, 0.65f ), 1 );
			Paint.ClearBrush();
			for ( int r = 0; r < rows; r++ )
				for ( int c = 0; c < cols; c++ )
				{
					var x = ox + c * (slot + 2);
					var y = oy + r * (slot + 2);
					Paint.DrawRect( new Rect( x, y, slot, slot ), 2 );
				}
		}
	}
}