namespace MinicsUI.Connector;

public partial class HubReceiver
{
    public HubReceiver(Hardwares hardwares, TemperatureConfigs configs, AlarmRealtime alarmRealtime, DatabaseCleaner databaseCleaner)
    {
        _hardwares = hardwares;
        _configs = configs;
        _alarmRealtime = alarmRealtime;
        _dataUpdateQueue ??= new(DataUpdateQueueHandler);
        _databaseCleaner = databaseCleaner;
    }

    private readonly DatabaseCleaner _databaseCleaner;
    private readonly Hardwares _hardwares;
    private readonly TemperatureConfigs _configs;
    private readonly AlarmRealtime _alarmRealtime;
    private readonly EventQueue<(byte, byte, ChannelData)> _dataUpdateQueue;

    public void UpdateDataBaseInfo(int duration, DateTime dateTime)
    {
        _databaseCleaner.KeepRange = (uint)duration;
        _databaseCleaner.LastCheckDate = dateTime;
    }

    public void UpdateSingleChannel(byte mini8Index, byte channelIndex, ChannelData channelData)
    {
        if (!_hardwares.Mini8Channels.TryGetValue(mini8Index, out var channels) || channels is null)
            return;
        if (!channels.TryGetValue(channelIndex, out Channel? channel) || channel is null)
            return;

        channelData.Adapt(channel);
    }

    public void UpdateChannels(byte key, List<ChannelData> value)
    {
        if (!_hardwares.Mini8s.TryGetValue(key, out Mini8Info? mini8) || mini8 is null || string.IsNullOrEmpty(mini8.Name))
            return;

        _hardwares.Mini8Channels[key] ??= [];

        foreach (ChannelData channelModel in value)
        {
            if (!_hardwares.Mini8Channels[key].TryGetValue(channelModel.ChannelIndex, out Channel? channel) || channel is null)
            {
                //channel = new(mini8.Name);
                channel = new();
                channelModel.Adapt(channel);
                _hardwares.Mini8Channels[key][channel.ChannelIndex] = channel;
            }
            channelModel.Adapt(channel);
        }
    }

    public void ClearFiles()
    {
        Application.Current.Dispatcher.Invoke(() =>
        {
            _configs.ConfigFiles?.Clear();
        });
    }

    public void UpdateFiles(TemperatureConfig value)
    {
        TempConfig tempConfig = new();
        value.Adapt(tempConfig);
        Application.Current.Dispatcher.Invoke(() =>
        {
            _configs.ConfigFiles.Add(tempConfig);
        });
    }

    public void UpdateAddress(byte key, Mini8Address address)
    {
        if (!_hardwares.Mini8s.TryGetValue(key, out Mini8Info? mini8) || mini8 is null)
            return;

        mini8.Address = address.Address;
        mini8.Port = address.Port;
    }

    public void CurrentFile(TemperatureConfig config)
    {
        if (config is null)
            return;

        TempConfig tempConfig = new();
        config.Adapt(tempConfig);

        CurrentTempConfig currentTempConfig = new()
        {
            Selector = TempConfigSelector.Manual,
            SelectedTime = DateTime.Now,
            ConfigFile = tempConfig,
        };
        _configs.CurrentConfigFile = currentTempConfig;
    }

    public void Mini8Connect(byte key, bool isConnect)
    {
        if (!_hardwares.Mini8s.TryGetValue(key, out Mini8Info? mini8) || mini8 is null)
            return;

        if (!mini8.Enable)
            return;

        mini8.IsConnected = isConnect;
    }

    public void AlarmNotify(byte mini8, byte channel, float temperature)
    {
        _alarmRealtime.InsertAlarm(mini8, channel, temperature);
    }

    public void AlarmTcBrockenNotify(byte mini8, byte channel)
    {
        _alarmRealtime.InsertTcBrocken(mini8, channel);
    }

    public void ChannelDataUpdate(byte mini8Index, byte channelIndex, ChannelData data)
        => _dataUpdateQueue.Enqueue(new(mini8Index, channelIndex, data));

    private void DataUpdateQueueHandler((byte mini8Index, byte channelIndex, ChannelData data) mini8Input)
    {
        if (!_hardwares.Mini8s.TryGetValue(mini8Input.mini8Index, out Mini8Info? mini8) || mini8 is null)
            return;

        if (!mini8.Enable)
            return;

        if (!_hardwares.Mini8Channels.TryGetValue(mini8Input.mini8Index, out var channels) || channels is null)
            return;

        if (!channels.TryGetValue(mini8Input.channelIndex, out Channel? channel) || channel is null)
            return;

        mini8Input.data.Adapt(channel);

        //Try Cancel Alarm 
        if (channel.Status.In(ChannelSuatus.Warning, ChannelSuatus.Normal))
            _alarmRealtime.CancelAlarm(mini8.Index, channel.ChannelIndex);

        Mini8Status finalStatus = Mini8Status.Normal;
        foreach (Channel item in channels.Values)
        {
            if (item.Inhibit == Inhibit.Disable)
                continue;

            switch (item.Status)
            {
                case ChannelSuatus.Error:
                    mini8.Status = Mini8Status.Error;
                    return;
                case ChannelSuatus.Warning:
                    finalStatus = Mini8Status.Warning;
                    continue;
                default:
                    continue;
            }
        }

        mini8.Status = finalStatus;
    }
}