using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TeamAAS_VP.Core.Lights;
using TeamAAS_VP.Interfaces;
using TeamAAS_VP.Models;
using TeamAAS_VP.Models.Lights;
namespace TeamAAS_VP.Services
{
///
/// 管理多个灯光控制器及其全局通道的服务。
/// 提供控制器注册/注销、全局通道的亮度与开关控制以及批量连接/断开功能。
///
public class LightManagerService : ILightManagerService
{
///
/// 本地按控制器ID索引的控制器集合。
/// 键:控制器ID,值:实现 的实例。
///
private readonly Dictionary _controllers;
///
/// 全局通道映射。键为全局通道ID,值为具体的通道实例。
///
private readonly Dictionary _globalChannels;
///
/// 不同灯具型号对应的工厂方法字典。
/// 键:灯具型号,值:创建控制器的工厂函数 (id, config) => ILightController
///
private readonly Dictionary> _controllerFactories;
///
/// 下一个可分配的全局通道ID(用于冲突时自动分配)。
///
private int _nextGlobalChannelId = 0;
///
/// 只读访问已注册的控制器集合。
///
public IReadOnlyDictionary Controllers => _controllers;
///
/// 只读访问全局通道映射。
///
public IReadOnlyDictionary GlobalChannels => _globalChannels;
///
/// 当控制器被添加时触发的事件。
///
public event EventHandler ControllerAdded;
///
/// 当控制器被移除时触发的事件。
///
public event EventHandler ControllerRemoved;
///
/// 当某个全局通道状态(开/关/亮度)变化时触发的事件。
///
public event EventHandler ChannelStatusChanged;
///
/// 构造函数,初始化内部字典并注册默认的控制器工厂。
///
public LightManagerService()
{
_controllers = new Dictionary();
_globalChannels = new Dictionary();
_controllerFactories = new Dictionary>();
RegisterDefaultFactories();
}
///
/// 注册默认的控制器工厂(当前含 KCS 型号)。
///
private void RegisterDefaultFactories()
{
// 注册KCS控制器工厂
RegisterControllerFactory(LightModel.KCS_KDC_12V60W_4T, (id, config) =>
{
if (config == null) throw new ArgumentNullException(nameof(config));
// 使用配置里的串口配置创建协议实现,再创建控制器实例
var protocol = new SerialPortProtocol(config.SerialPortConfig);
return new KCSLightController(id, protocol, config.ChannelCount,config);
});
}
///
/// 手动注册一个控制器工厂,用于扩展支持更多型号。
///
/// 灯具模型
/// 工厂函数:根据 id 和配置返回 实例
public void RegisterControllerFactory(LightModel model, Func factory)
{
_controllerFactories[model] = factory;
}
///
/// 异步注册控制器并建立其通道到全局通道ID的映射。
///
/// 控制器ID(局部)
/// 控制器配置
/// 已创建的控制器实例
/// 当配置为 null 时抛出
/// 当同ID已存在或未注册工厂时抛出
/// 当工厂返回 null 时抛出
public async Task RegisterControllerAsync(int id, TeamAAS_VP.Models.Lights.LightControllerConfig configuration)
{
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
if (_controllers.ContainsKey(id))
throw new ArgumentException($"Controller with id '{id}' already exists");
if (!_controllerFactories.TryGetValue(configuration.LightModel, out var factory))
throw new ArgumentException($"No factory registered for model '{configuration.LightModel}'");
var controller = factory(id, configuration);
if (controller == null)
throw new InvalidOperationException("Factory returned null controller");
// 将控制器加入管理集合
_controllers[id] = controller;
// 映射控制器内部通道到全局通道ID
for (int i = 0; i < controller.Channels.Count; i++)
{
var channelConfig = configuration.ChannelConfigs[i];
int globalIndex = channelConfig.GlobalIndex;
// 若指定的全局ID已被占用,则自动分配下一个可用ID
if (_globalChannels.ContainsKey(globalIndex))
{
// 自动重新分配全局ID
globalIndex = _nextGlobalChannelId++;
}
else if (globalIndex >= _nextGlobalChannelId)
{
// 若指定ID大于等于当前_nextGlobalChannelId,则推进_nextGlobalChannelId以避免重复
_nextGlobalChannelId = globalIndex + 1;
}
// 如果配置中的GlobalIndex与最终分配不一致,则更新配置(保持配置与运行时一致)
if (channelConfig.GlobalIndex != globalIndex)
{
channelConfig.GlobalIndex = globalIndex;
}
// 在全局映射表中建立映射:全局ID -> 控制器通道实例
_globalChannels[globalIndex] = controller.Channels[i];
}
// 通知订阅方有新控制器添加
ControllerAdded?.Invoke(this, new LightControllerEventArgs(controller));
return controller;
}
///
/// 注销指定ID的控制器,断开并释放资源,同时移除其全局通道映射。
///
/// 要注销的控制器ID
/// 如果存在并成功注销返回 true,否则 false
public async Task UnregisterControllerAsync(int controllerId)
{
if (!_controllers.TryGetValue(controllerId, out var controller))
return false;
// 找到属于该控制器的全局通道键并移除
var channelsToRemove = _globalChannels
.Where(kvp => controller.Channels.Contains(kvp.Value))
.Select(kvp => kvp.Key)
.ToList();
foreach (var channelId in channelsToRemove)
{
_globalChannels.Remove(channelId);
}
// 从管理集合中移除控制器并断开连接、释放资源
_controllers.Remove(controllerId);
await controller.DisconnectAsync();
controller.Dispose();
// 通知订阅方控制器已移除
ControllerRemoved?.Invoke(this, new LightControllerEventArgs(controller));
return true;
}
///
/// 设置指定全局通道的亮度值。
///
/// 全局通道ID
/// 亮度(由具体实现定义的范围)
/// 操作是否成功
public async Task SetGlobalChannelBrightnessAsync(int globalChannelId, int brightness)
{
if (!_globalChannels.TryGetValue(globalChannelId, out var channel))
return false;
var result = await channel.SetBrightnessAsync(brightness);
// 触发状态变化事件,通知外部当前通道的开关与亮度状态
ChannelStatusChanged?.Invoke(this, new LightChannelEventArgs(channel, channel.IsOn, channel.Brightness));
return result;
}
///
/// 打开指定的全局通道。
///
/// 全局通道ID
/// 操作是否成功
public async Task TurnOnGlobalChannelAsync(int globalChannelId)
{
if (!_globalChannels.TryGetValue(globalChannelId, out var channel))
return false;
var result = await channel.TurnOnAsync();
ChannelStatusChanged?.Invoke(this, new LightChannelEventArgs(channel, channel.IsOn, channel.Brightness));
return result;
}
///
/// 关闭指定的全局通道。
///
/// 全局通道ID
/// 操作是否成功
public async Task TurnOffGlobalChannelAsync(int globalChannelId)
{
if (!_globalChannels.TryGetValue(globalChannelId, out var channel))
return false;
var result = await channel.TurnOffAsync();
ChannelStatusChanged?.Invoke(this, new LightChannelEventArgs(channel, channel.IsOn, channel.Brightness));
return result;
}
///
/// 异步连接所有已注册的控制器。
///
/// 当所有控制器连接成功返回 true;任一失败返回 false。
public async Task ConnectAllAsync()
{
var tasks = _controllers.Values.Select(c => c.ConnectAsync());
var results = await Task.WhenAll(tasks);
return results.All(r => r);
}
///
/// 异步断开所有已注册的控制器(不会销毁控制器实例)。
///
/// 操作完成后返回 true。
public async Task DisconnectAllAsync()
{
foreach (var controller in _controllers.Values)
{
await controller.DisconnectAsync();
}
return true;
}
///
/// 将当前配置保存到指定文件(未实现)。
///
/// 目标文件路径
/// 完成任务
public Task SaveConfigurationAsync(string filePath)
{
// TODO: 实现配置保存逻辑(序列化控制器与通道映射)
return Task.CompletedTask;
}
///
/// 从指定文件加载配置(未实现)。
///
/// 配置文件路径
/// 完成任务
public Task LoadConfigurationAsync(string filePath)
{
// TODO: 实现配置加载逻辑(反序列化并调用 RegisterControllerAsync)
return Task.CompletedTask;
}
}
}