using RTCommunicatorBase;
using System.Text;
using TLVProtocal;
using UniversalNetFrame451.IO;

namespace AlarmInfoServerSim.Services;

public class InfoSendingService : IInfoSendingService, ITlvProvider, IDisposable
{
    private readonly ILogService _logService;
    private readonly ISharedConfig _sharedConfig;
    private readonly ITlvCommunicatorServer _server;

    private bool _isConnected;
    private bool disposedValue;

    public InfoSendingService(ILogService logService, ISharedConfig sharedConfig)
    {
        _logService = logService;
        _sharedConfig = sharedConfig;

        _server = TlvFactory.GetTlvServer();
        if (!_server.Initialize(this))
        {
            throw new InvalidOperationException("Failed to initialize tcp server");
        }

        Open();
    }

    public event EventHandler<(bool, TcpConnection)>? ConnectionChanged;

    public event EventHandler<(ushort, TlvData)>? DataReceived;

    public void Open()
    {
        if(_sharedConfig.BasicInfo is null)
        {
            _logService.Log("Cannot find BasicInfo file! Please make sure it is existing!");
            return;
        }

        if (!_server.Open(_sharedConfig.BasicInfo.RTServerAddress, _sharedConfig.BasicInfo.RTServerPort))
        {
            _logService.Log($"Failed to start TCP server in {_sharedConfig.BasicInfo.RTServerAddress}:{_sharedConfig.BasicInfo.RTServerPort}");
        }
    }

    public void Send(byte tag, ST_ALARM alarm)
    {
        if(!_isConnected)
        {
            _logService.Log("Cannot send information due to disconnected status");
            return;
        }

        if(!_server.Send(tag, alarm))
        {
            _logService.Log("Cannot send information due to unknown reason");
        }
    }

    public void Connected(TcpConnection connection)
    {
        _isConnected = true;
        ConnectionChanged?.Invoke(null, (_isConnected, connection));
    }

    public void Disconnected(TcpConnection connection)
    {
        _isConnected = false;
        ConnectionChanged?.Invoke(null, (_isConnected, connection));
    }

    public void Received(TlvData data)
    {
        if (data.RawData is null || data.RawData.Length == 0)
        {
            _logService.Log("Received RawData is null");
            return;
        }

        if(data.Tag==1)
        {
            DataReceived?.Invoke(null,(data.Tag, data));
        }
    }

    public TlvData RequestReply(TlvData tlvData)
    {
        throw new NotImplementedException();
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                // TODO: dispose managed state (managed objects)
                _server.Dispose();
            }

            // TODO: free unmanaged resources (unmanaged objects) and override finalizer
            // TODO: set large fields to null
            disposedValue = true;
        }
    }

    // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
    // ~InfoSendingService()
    // {
    //     // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
    //     Dispose(disposing: false);
    // }

    public void Dispose()
    {
        // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
        Dispose(disposing: true);
        GC.SuppressFinalize(this);
    }
}
