using Microsoft.AspNetCore.SignalR;
using RobotNet.Script.Shares;
using RobotNet.ScriptManager.Helpers;
using RobotNet.ScriptManager.Hubs;
using RobotNet.ScriptManager.Models;

namespace RobotNet.ScriptManager.Services;

public class ScriptTaskManager(ScriptGlobalsManager globalsManager, IHubContext<ScriptTaskHub> scriptHub)
{
    private readonly List<ScriptTaskData> ScriptTaskDatas = [];
    private readonly Dictionary<string, ScriptTask> ScriptTasks = [];

    public void Reset()
    {
        ScriptTaskDatas.Clear();
        foreach (var task in ScriptTasks.Values)
        {
            task.Dispose();
        }
        ScriptTasks.Clear();
        GC.Collect();
    }

    public void LoadTasks(IEnumerable<ScriptTaskData> tasks)
    {
        Reset();
        ScriptTaskDatas.AddRange(tasks);
        foreach (var task in tasks)
        {
            ScriptTasks.Add(task.Name, new ScriptTask(task, ScriptConfiguration.ScriptOptions, globalsManager.Globals, globalsManager.GetRobotNetTask(task.Name)));
        }
    }

    public IEnumerable<ScriptTaskDto> GetTaskDatas() => [.. ScriptTaskDatas.Select(t => new ScriptTaskDto(t.Name, t.Interval, t.Code))];

    public void StartAll(CancellationToken cancellationToken = default)
    {
        foreach (var task in ScriptTasks.Values)
        {
            task.Start(cancellationToken);
        }
    }

    public void StopAll()
    {
        foreach (var task in ScriptTasks.Values)
        {
            task.Stop();
        }
    }

    public IDictionary<string, bool> GetTaskStates()
    {
        return ScriptTasks.ToDictionary(task => task.Key, task => !task.Value.Paused);
    }

    public bool Pause(string name)
    {
        if (ScriptTasks.TryGetValue(name, out var task))
        {
            task.Pause();
            _ = Task.Factory.StartNew(async Task () =>
            {
                await scriptHub.Clients.All.SendAsync("TaskPaused", name);
            }, TaskCreationOptions.LongRunning);
            return true;
        }
        else
        {
            return false;
        }
    }

    public bool Resume(string name)
    {
        if(ScriptTasks.TryGetValue(name, out var task))
        {
            task.Resume();
            _ = Task.Factory.StartNew(async Task () =>
            {
                await scriptHub.Clients.All.SendAsync("TaskResumed", name);
            }, TaskCreationOptions.LongRunning);
            return true;
        }
        else
        {
            return false;
        }
    }
}
