using System.IO.Abstractions; using System.Net; using System.Net.Sockets; using Quadarax.Foundation.Core.Logging; using Quadarax.Foundation.Core.Object; namespace qmonlib { public abstract class QMonHostBase : DisposableObject where TConfiguration : QMonHostConfiguration { #region *** Fields *** private bool _isEnabled; private ILog? _log; private UdpClient? _udpClientGeneral; private UdpClient? _udpClientData; private Timer? _timerGeneral; private Timer? _timerData; #endregion #region *** Properties *** protected TConfiguration Configuration { get; } protected abstract Uri UriGeneral { get; } protected abstract Uri UriData { get; } protected abstract TimeSpan IntervalGeneral {get; } protected abstract TimeSpan? IntervalData { get; } protected UdpClient UdpClientGeneral => _udpClientGeneral ?? throw new InvalidOperationException("UDP client channel General not open."); protected UdpClient UdpClientData => _udpClientData ?? throw new InvalidOperationException("UDP client channel Data not open."); public bool IsEnabled { get => _isEnabled; set => SetEnabled(value); } protected Quadarax.Foundation.Core.Json.Binder Binder { get; } = new Quadarax.Foundation.Core.Json.Binder(new FileSystem(),false,true,100); #endregion #region *** Constructors *** protected QMonHostBase(TConfiguration configuration, ILogger? externalLogger) { Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _log = externalLogger?.GetLogger(GetType()); SetEnabled(configuration.Enabled); } #endregion #region *** Private Operations *** protected void Open() { if (!_isEnabled) return; if (_udpClientGeneral != null) throw new InvalidOperationException("UDP client channel General already open. Close first."); if (_udpClientData != null) throw new InvalidOperationException("UDP client channel Data already open. Close first."); _udpClientGeneral = CreateUdpClient(UriGeneral); _udpClientData = CreateUdpClient(UriData); _timerGeneral = new Timer(OnTimerGeneral, this, IntervalGeneral, IntervalGeneral); if (IntervalData.HasValue) _timerData = new Timer(OnTimerData, this, IntervalData.Value, IntervalData.Value); OnOpen(); } protected void Close() { if (!_isEnabled) return; if (_udpClientGeneral != null) { _timerGeneral?.Dispose(); _udpClientGeneral.Close(); _udpClientGeneral.Dispose(); _udpClientGeneral = null; _timerGeneral = null; } if (_udpClientData != null) { _timerData?.Dispose(); _udpClientData.Close(); _udpClientData.Dispose(); _udpClientData = null; _timerData = null; } OnClose(); } protected abstract void OnOpen(); protected abstract void OnClose(); protected abstract void OnTimerData(object? state); protected abstract void OnTimerGeneral(object? state); #endregion protected void SetEnabled(bool value) { if (value == _isEnabled) return; _isEnabled = value; if (_isEnabled) Open(); else Close(); } protected override void OnDisposing() { Close(); } protected void Log(LogSeverityEnum type, string message, Exception? e = null) { _log?.Log(type, message, e); } protected abstract UdpClient CreateUdpClient(Uri targetUri); } }