using RTCommunicatorBase;
using RTCommunicatorTLV;

namespace MinicsConsole.Connector;

public class RTNotifier(Hardwares hardwares) : IMini8DataNotifier, IDisposable
{
    private ITlvCommunicatorServer? _server;
    public string Name { get; set; } = "RT TLV";

    public bool Initialize(ITlvProvider tlvProvider)
    {
        if (this._server is not null)
            return false;

        this._server = TlvFactory.GetTlvServer();
        this._server.Initialize(tlvProvider);
        return true;
    }

    public bool Open(string IP, ushort port)
    {
        if (this._server is null)
            return false;

        return this._server.Open(IP, port);

    }
    public void Dispose()
    {
        this._server?.Dispose();
        this._server = null;
    }

    void IMini8DataNotifier.ChannelInfoNotify(byte mini8, byte channel, ChannelData channelData)
    {
        ST_CHANNEL data = new()
        {
            Mini8Index = mini8,
            ChannelIndex = channel,
            PV = channelData.PV,
            Caps = channelData.Caps,
            Floor = channelData.Floor,
            WorkingOutput = channelData.WorkingOutput,
        };

        this._server?.Send(Tags.ChannelRealtimeDataNotify, data);
    }

    void IMini8DataNotifier.AlarmNotify(byte mini8, byte channel, float temperature)
    {
        if (!hardwares.Mini8Channels.TryGetSubValue(mini8, channel, out ChannelData? channelData) || channelData is null)
            return;

        RTCommunicatorBase.AlarmType alarmType;
        if (temperature > channelData.Caps)
            alarmType = RTCommunicatorBase.AlarmType.CapsOverFlow;
        else if (temperature < channelData.Floor)
            alarmType = RTCommunicatorBase.AlarmType.FloorOverFlow;
        else
            alarmType = RTCommunicatorBase.AlarmType.Undefined;

        ST_ALARM alarm = new()
        {
            Mini8Index = mini8,
            ChannelIndex = channel,
            PV = temperature,
            Caps = channelData.Caps,
            Floor = channelData.Floor,
            WorkingOutput = channelData.WorkingOutput,
            AlarmType = alarmType
        };
        Task.Factory.StartNew(() =>
        {
            this._server?.Send(Tags.ChannelAlarmNotify, alarm);
        });
    }
    void IMini8DataNotifier.AlarmTcBrockenNotify(byte mini8, byte channel)
    {
        ST_ALARM alarm = new()
        {
            Mini8Index = mini8,
            ChannelIndex = channel,
            AlarmType = RTCommunicatorBase.AlarmType.TcBroken,
        };

        this._server?.Send(Tags.ChannelAlarmNotify, alarm);
    }
    void IMini8DataNotifier.Mini8ConnectNotify(byte mini8, bool connected)
    {
        byte tag = connected ? Tags.Mini8ConnectNotify : Tags.Mini8DisconnectNotify;
        this._server?.Send(tag, mini8);
    }
}