using Microsoft.AspNetCore.SignalR;
using RobotNet10.ScriptEngine.Shared;
using RobotNet10.Shared;
namespace RobotNet10.ScriptEngine.Hubs;
///
/// SignalR hub for ScriptEngine management operations.
///
///
/// Initializes a new instance of ScriptManagerHub.
///
public class ScriptManagerHub(ScriptEngine _scriptEngine) : Hub
{
///
/// Gets the current state of the ScriptEngine.
///
public Task GetState()
{
return Task.FromResult(_scriptEngine.State);
}
///
/// Builds scripts from all files. Only allowed when state is Idle or BuildError.
///
public Task Build()
{
return Task.FromResult(_scriptEngine.Build());
}
///
/// Starts the ScriptEngine. Only allowed when state is Ready.
///
public Task Start()
{
return Task.FromResult(_scriptEngine.Start());
}
///
/// Stops the ScriptEngine. Only allowed when state is Running.
///
public Task Stop()
{
return Task.FromResult(_scriptEngine.Stop());
}
///
/// Resets the ScriptEngine. Allowed from Idle, Ready, BuildError, Running, or Fault.
///
public Task Reset()
{
return Task.FromResult(_scriptEngine.Reset());
}
#region VariableManager Methods
///
/// Gets all script variables.
///
public Task GetScriptVariables()
{
return Task.FromResult(_scriptEngine.VariableManager.GetVariables().ToArray());
}
///
/// Finds specific script variables by names.
///
public Task FindScriptVariables(string[] names)
{
return Task.FromResult(_scriptEngine.VariableManager.GetVariables(names).ToArray());
}
///
/// Sets the value of a script variable by name.
///
public Task SetValue(string name, string value)
{
return Task.FromResult(_scriptEngine.VariableManager.SetValue(name, value));
}
#endregion
#region TaskManager Methods
///
/// Gets all script tasks.
///
public Task GetScriptTasks()
{
return Task.FromResult(_scriptEngine.TaskManager.GetScriptTasks());
}
///
/// Finds specific script tasks by names.
///
public Task FindScriptTasks(string[] names)
{
return Task.FromResult(_scriptEngine.TaskManager.FindScriptTasks(names));
}
///
/// Enables a task (resumes if paused, starts if stopped).
///
public Task EnableTask(string name)
{
return Task.FromResult(_scriptEngine.TaskManager.EnableTask(name));
}
///
/// Disables a task (pauses if running).
///
public Task DisableTask(string name)
{
return Task.FromResult(_scriptEngine.TaskManager.DisableTask(name));
}
#endregion
#region MissionManager Methods
///
/// Gets all script missions.
///
public Task GetScriptMissions()
{
return Task.FromResult(_scriptEngine.MissionManager.GetScriptMissions());
}
///
/// Finds specific script missions by names.
///
public Task FindScriptMissions(string[] names)
{
return Task.FromResult(_scriptEngine.MissionManager.FindScriptMissions(names));
}
///
/// Creates a mission instance with parameters provided as a dictionary.
///
/// The name of the mission model.
/// Dictionary of parameter values keyed by parameter name (as strings).
/// MessageResult containing the mission ID if successful.
public async Task> CreateMission(string name, IDictionary args)
{
if (string.IsNullOrWhiteSpace(name))
return new MessageResult(false, default, "Mission name cannot be null or empty");
if (args == null)
return new MessageResult(false, default, "Parameters cannot be null");
// Convert string dictionary to object dictionary
var missionModel = _scriptEngine.MissionManager.GetMissionModel(name);
if (missionModel == null)
return new MessageResult(false, default, $"Mission model '{name}' not found");
var parameters = new Dictionary();
foreach (var paramModel in missionModel.Parameters)
{
// Skip CancellationToken parameters
if (paramModel.Type == typeof(CancellationToken))
continue;
if (args.TryGetValue(paramModel.Name, out var stringValue))
{
try
{
object? convertedValue = null;
if (!string.IsNullOrEmpty(stringValue) && stringValue != "null")
{
if (paramModel.Type == typeof(string))
{
convertedValue = stringValue;
}
else if (paramModel.Type.IsEnum)
{
convertedValue = Enum.Parse(paramModel.Type, stringValue, true);
}
else
{
convertedValue = Convert.ChangeType(stringValue, paramModel.Type);
}
}
parameters[paramModel.Name] = convertedValue;
}
catch (Exception ex)
{
var errorMessage = $"Failed to convert parameter '{paramModel.Name}' value '{stringValue}' to type '{paramModel.Type.Name}': {ex.Message}";
// Log error via ConsoleHubContext if available
// Note: We don't have direct access to ConsoleHubContext here, but error is returned to client
return new MessageResult(false, default, errorMessage);
}
}
else
{
// Use default value if not provided
parameters[paramModel.Name] = paramModel.DefaultValue;
}
}
return await Task.FromResult(_scriptEngine.MissionManager.CreateMission(name, parameters));
}
///
/// Cancels a running or paused mission.
///
/// The ID of the mission instance to cancel.
/// The reason for cancellation.
/// True if the mission was canceled successfully, false otherwise.
public Task CancelMission(Guid id, string reason)
{
var mission = _scriptEngine.MissionManager.GetMission(id);
if (mission == null)
return Task.FromResult(false);
try
{
mission.Cancel(reason);
return Task.FromResult(true);
}
catch
{
return Task.FromResult(false);
}
}
#endregion
}