using RemSox.Kernel.Processing;
using RemSox.Kernel.UI.GUI.UIEelements;
using RemSox.Kernel.UI.GUI.UIEelements.Controls;
using RemSox.Kernel.UI.GUI.UIEelements.Shapes;
using RemSox.Kernel.UI.GUI.Windows;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using YesNt.Interpreter.Runtime;
using YesNt.Interpreter.Utilities;
using ShapesRectangle = RemSox.Kernel.UI.GUI.UIEelements.Shapes.Rectangle;
namespace RemSox.Kernel.Utils;
///
///
/// Registers all YesNt statements that expose the WindowManager / UI element API.
///
///
/// All ui_* and win_* statements support two argument styles:
///
positional: ui_rect ${id} 20 20 100 60 0 128 255
///
named: ui_rect ${id} x=20 y=20 w=100 h=60 r=0 g=128 b=255
///
///
/// Commas are treated as whitespace in both modes, so you can write:
///
ui_rect ${id} x=20,y=20,w=100,h=60,r=0,g=128,b=255
///
///
/// If any argument contains '=', the statement parses in named mode
/// (order-independent). Otherwise, positional mode is used.
///
///
/// Substitutions:
///
%win_last_id expands to the id of the last created window
///
%ui_last_id expands to the id of the last created UI element
///
///
public class YesNtWindowStatements(Process ownerProcess)
{
private readonly Dictionary windows = [];
private readonly Dictionary uiElements = [];
private int lastWindowId;
private int lastUiId;
public void Register(YesNtInterpreter interpreter)
{
RegisterWindowStatements(interpreter);
RegisterButtonStatement(interpreter);
RegisterCheckBoxStatement(interpreter);
RegisterLabelStatement(interpreter);
RegisterTextBoxStatement(interpreter);
RegisterRadioButtonStatement(interpreter);
RegisterProgressBarStatement(interpreter);
RegisterSliderStatement(interpreter);
RegisterPanelStatement(interpreter);
RegisterLineStatement(interpreter);
RegisterRectStatement(interpreter);
RegisterCircleStatement(interpreter);
RegisterRemoveStatement(interpreter);
RegisterLastIdSubstitutions(interpreter);
}
// --- Argument parser ---
private static string[] ParseTokens(string input)
{
return input.Split([' ', ','], StringSplitOptions.RemoveEmptyEntries);
}
private static bool IsNamed(string[] tokens)
{
foreach (string t in tokens)
{
if (t.Contains('='))
{
return true;
}
}
return false;
}
private static bool TryGetInt(string[] tokens, bool named, string name, int pos, out int value)
{
value = 0;
if (named)
{
string prefix = name + '=';
foreach (string t in tokens)
{
if (t.StartsWith(prefix) && int.TryParse(t.AsSpan(prefix.Length), out value))
{
return true;
}
}
return false;
}
if (pos < tokens.Length && int.TryParse(tokens[pos], out value))
{
return true;
}
return false;
}
private static bool TryGetString(string[] tokens, bool named, string name, int pos, out string value)
{
value = string.Empty;
if (named)
{
string prefix = name + '=';
foreach (string t in tokens)
{
if (t.StartsWith(prefix))
{
value = t[prefix.Length..].FromSafeString();
return true;
}
}
return false;
}
if (pos < tokens.Length)
{
value = tokens[pos].FromSafeString();
return true;
}
return false;
}
// --- Window statements ---
private void RegisterWindowStatements(YesNtInterpreter interpreter)
{
// win_create "Title" w h [chrome=true|false]
interpreter.AddStatement(
new StatementInformation("win_create", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
{ Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
string trimmed = args.Trim();
string title;
int w, h;
bool chrome = true;
if (trimmed.StartsWith('"'))
{
int end = trimmed.IndexOf('"', 1);
if (end < 0)
{
context.Exit("[win_create] Missing closing quote", false);
return;
}
title = trimmed[1..end];
string[] tokens = ParseTokens(trimmed[(end + 1)..]);
bool named = IsNamed(tokens);
if (!TryGetInt(tokens, named, "w", 0, out w) || !TryGetInt(tokens, named, "h", 1, out h))
{
context.Exit("[win_create] Expected width and height", false);
return;
}
if (TryGetString(tokens, named, "chrome", 2, out string chromeStr))
{
_ = bool.TryParse(chromeStr, out chrome);
}
}
else
{
string[] tokens = ParseTokens(trimmed);
bool named = IsNamed(tokens);
if (!TryGetString(tokens, named, "title", 0, out title) ||
!TryGetInt(tokens, named, "w", 1, out w) ||
!TryGetInt(tokens, named, "h", 2, out h))
{
context.Exit("[win_create] Usage: win_create \"Title\" w h [chrome=false]", false);
return;
}
if (TryGetString(tokens, named, "chrome", 3, out string chromeStr))
{
_ = bool.TryParse(chromeStr, out chrome);
}
}
Window win = WindowManager.CreateWindow(ownerProcess, title, new Size(w, h));
win.HasChrome = chrome;
int id = lastWindowId = win.Id;
windows[id] = win;
});
// win_close id
interpreter.AddStatement(
new StatementInformation("win_close", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
{ Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
if (TryGetWindow(args, out Window? win))
{
WindowManager.CloseWindow(win);
_ = windows.Remove(win.Id);
}
});
// win_flush id
interpreter.AddStatement(
new StatementInformation("win_flush", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
{ Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
if (TryGetWindow(args, out Window? win))
{
win.Flush();
}
});
// win_title id "New Title"
interpreter.AddStatement(
new StatementInformation("win_title", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
{ Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
string trimmed = args.Trim();
string[] tokens = ParseTokens(trimmed);
bool named = IsNamed(tokens);
if (!TryGetInt(tokens, named, "id", 0, out int id) || !windows.TryGetValue(id, out Window? win))
{
return;
}
string title;
if (trimmed.Contains('"'))
{
int start = trimmed.IndexOf('"') + 1;
int end = trimmed.IndexOf('"', start);
title = end >= 0 ? trimmed[start..end] : trimmed[start..];
}
else
{
_ = TryGetString(tokens, named, "title", 1, out title);
}
win.Title = title;
});
// win_autoflush id true|false
interpreter.AddStatement(
new StatementInformation("win_autoflush", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
{ Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
string[] tokens = ParseTokens(args.Trim());
bool named = IsNamed(tokens);
if (TryGetInt(tokens, named, "id", 0, out int id) &&
TryGetString(tokens, named, "enabled", 1, out string enabledStr) &&
bool.TryParse(enabledStr, out bool enabled) &&
windows.TryGetValue(id, out Window? win))
{
win.AutoFlush = enabled;
}
});
// win_chrome id true|false
interpreter.AddStatement(
new StatementInformation("win_chrome", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
{ Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
string[] tokens = ParseTokens(args.Trim());
bool named = IsNamed(tokens);
if (TryGetInt(tokens, named, "id", 0, out int id) &&
TryGetString(tokens, named, "chrome", 1, out string chromeStr) &&
bool.TryParse(chromeStr, out bool chrome) &&
windows.TryGetValue(id, out Window? win))
{
win.HasChrome = chrome;
}
});
// win_focus id
interpreter.AddStatement(
new StatementInformation("win_focus", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
{ Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
if (TryGetWindow(args, out Window? win))
{
WindowManager.FocusWindow(win);
}
});
// win_move id x y
interpreter.AddStatement(
new StatementInformation("win_move", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
{ Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
string[] tokens = ParseTokens(args.Trim());
bool named = IsNamed(tokens);
if (TryGetInt(tokens, named, "id", 0, out int id) &&
TryGetInt(tokens, named, "x", 1, out int x) &&
TryGetInt(tokens, named, "y", 2, out int y) &&
windows.TryGetValue(id, out Window? win))
{
win.Position = new Point(x, y);
}
});
// win_resize id w h
interpreter.AddStatement(
new StatementInformation("win_resize", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
{ Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
string[] tokens = ParseTokens(args.Trim());
bool named = IsNamed(tokens);
if (TryGetInt(tokens, named, "id", 0, out int id) &&
TryGetInt(tokens, named, "w", 1, out int w) &&
TryGetInt(tokens, named, "h", 2, out int h) &&
windows.TryGetValue(id, out Window? win))
{
win.Size = new Size(w, h);
}
});
// win_invalidate_all
interpreter.AddStatement(
new StatementInformation("win_invalidate_all", YesNt.Interpreter.Enums.SearchMode.Contains, YesNt.Interpreter.Enums.SpaceAround.None)
{ Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) => WindowManager.InvalidateAll());
}
// --- Control statements ---
private void RegisterButtonStatement(YesNtInterpreter interpreter)
{
interpreter.AddStatement(
new StatementInformation("ui_button", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
{ Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
if (!TryGetWindowAndArgs(args, out Window? win, out string[] tokens, out bool named))
{
return;
}
if (!TryGetInt(tokens, named, "x", 0, out int x) ||
!TryGetInt(tokens, named, "y", 1, out int y) ||
!TryGetInt(tokens, named, "w", 2, out int w) ||
!TryGetInt(tokens, named, "h", 3, out int h) ||
!TryGetString(tokens, named, "label", 4, out string label))
{
context.Exit("[ui_button] Usage: ui_button winId x y w h \"Label\" [r g b]", false);
return;
}
Color color = ParseColor(tokens, named, 5);
Button button = win.CreateUIElement