namespace Terminal.Gui.App;
using System;
///
/// Provides helper methods for executing single-phase and result-producing workflows in the Cancellable Work Pattern (CWP).
///
///
///
/// Used for workflows that allow customization or cancellation, such as command execution
/// (e.g., ) or scheme resolution (e.g., ).
/// The method handles workflows without results, while
/// handles workflows producing results.
///
///
///
public static class CWPWorkflowHelper
{
///
/// Executes a single-phase CWP workflow with a virtual method, event, and optional default action.
///
/// The type of the result in the event arguments.
/// The virtual method invoked first, returning true to mark the workflow as handled.
/// The event handler to invoke, or null if no handlers are subscribed.
/// The event arguments containing a result and handled status.
/// The default action to execute if the workflow is not handled, or null if none.
/// True if the workflow was handled, false if not, or null if no event handlers are subscribed.
///
/// Thrown if or is null.
///
///
///
/// ResultEventArgs<bool> args = new();
/// Func<ResultEventArgs<bool>, bool> onAccepting = _ => false;
/// EventHandler<ResultEventArgs<bool>>? acceptingHandler = null;
/// Action? defaultAction = () => args.Result = true;
/// bool? handled = CWPWorkflowHelper.Execute(onAccepting, acceptingHandler, args, defaultAction);
///
///
public static bool? Execute (
Func, bool> onMethod,
EventHandler>? eventHandler,
ResultEventArgs args,
Action? defaultAction = null)
{
ArgumentNullException.ThrowIfNull (onMethod);
ArgumentNullException.ThrowIfNull (args);
bool handled = onMethod (args) || args.Handled;
if (handled)
{
return true;
}
eventHandler?.Invoke (null, args);
if (args.Handled)
{
return true;
}
if (defaultAction is {})
{
defaultAction ();
return true;
}
return eventHandler is null ? null : false;
}
///
/// Executes a CWP workflow that produces a result, suitable for methods like .
///
/// The type of the result, which may be a nullable reference type (e.g., ?).
/// The virtual method invoked first, returning true to mark the workflow as handled.
/// The event handler to invoke, or null if no handlers are subscribed.
/// The event arguments containing a result and handled status.
/// The default action that produces the result if the workflow is not handled.
/// The result from the event arguments or the default action.
///
/// Thrown if , , or is null.
///
///
/// Thrown if is null for non-nullable reference types when is true.
///
///
///
/// ResultEventArgs<Scheme?> args = new();
/// Func<ResultEventArgs<Scheme?>, bool> onGettingScheme = _ => false;
/// EventHandler<ResultEventArgs<Scheme?>>? gettingSchemeHandler = null;
/// Func<Scheme> defaultAction = () => SchemeManager.GetScheme("Base");
/// Scheme scheme = CWPWorkflowHelper.ExecuteWithResult(onGettingScheme, gettingSchemeHandler, args, defaultAction);
///
///
public static TResult ExecuteWithResult (
Func, bool> onMethod,
EventHandler>? eventHandler,
ResultEventArgs args,
Func defaultAction)
{
ArgumentNullException.ThrowIfNull (onMethod);
ArgumentNullException.ThrowIfNull (args);
ArgumentNullException.ThrowIfNull (defaultAction);
bool handled = onMethod (args) || args.Handled;
if (handled)
{
if (args.Result is null && !typeof (TResult).IsValueType && !Nullable.GetUnderlyingType (typeof (TResult))?.IsValueType == true)
{
throw new InvalidOperationException ("Result cannot be null for non-nullable reference types when Handled is true.");
}
return args.Result!;
}
eventHandler?.Invoke (null, args);
if (!args.Handled)
{
return defaultAction ();
}
if (args.Result is null && !typeof (TResult).IsValueType && !Nullable.GetUnderlyingType (typeof (TResult))?.IsValueType == true)
{
throw new InvalidOperationException ("Result cannot be null for non-nullable reference types when Handled is true.");
}
return args.Result!;
}
}