using System; using System.Collections.Generic; using System.Linq; using H.Formatters; using H.Pipes; using InABox.Integration.Logikal; using Newtonsoft.Json; namespace PRSLogikal { public class LogikalListener : IDisposable { private PipeServer _server; public LogikalServer Server { get; set; } public event LogikalLogEvent Log; private void DoLog(string message) => Log?.Invoke(this, new LogikalLogArguments(message)); public event EventHandler Disconnecting; public LogikalListener() { methods = new Dictionary { { LogikalMethod.Error, new LogikalMethodInfo(DoError) }, { LogikalMethod.Connect, new LogikalMethodInfo(Connect) }, { LogikalMethod.Login, new LogikalMethodInfo(Login) }, { LogikalMethod.Logout, new LogikalMethodInfo(Logout) }, { LogikalMethod.Disconnect, new LogikalMethodInfo(Disconnect) }, { LogikalMethod.ProjectCentres, new LogikalMethodInfo(GetProjectCentres) }, { LogikalMethod.Projects, new LogikalMethodInfo(GetProjects) }, { LogikalMethod.Phases, new LogikalMethodInfo(GetPhases) }, { LogikalMethod.ElevationSummary, new LogikalMethodInfo(GetElevationSummaries) }, { LogikalMethod.ElevationDetail, new LogikalMethodInfo(GetElevationDetails) }, { LogikalMethod.BOM, new LogikalMethodInfo(GetBOM) }, }; _server = new PipeServer("$logikal", formatter: new NewtonsoftJsonFormatter()); _server.ClientConnected += (o, args) => { DoLog($@"Client is now connected!"); }; _server.ClientDisconnected += (o, args) => { DoLog($@"Client disconnected"); }; _server.MessageReceived += (sender, args) => { DoLog($@"Client says: {args.Message.Method}: {args.Message.Payload}"); if (methods.TryGetValue(args.Message.Method, out var _info)) { var _request = FromMessage(_info.Type, args.Message); _info.Action(_request, args.Message.ID); } else DoError(new LogikalErrorRequest(LogikalStatus.Error, $"Invalid Message Method: {args.Message.Method}: {args.Message.Payload}"), args.Message.ID); }; _server.ExceptionOccurred += (sender, args) => { DoLog($@"Exception: {args.Exception.Message}"); }; } private interface ILogikalMethodInfo { Type Type { get; } Action Action { get; } } private class LogikalMethodInfo : ILogikalMethodInfo where T : LogikalRequest { public Type Type { get; } public Action Action { get; private set; } public LogikalMethodInfo(Action action) { Type = typeof(T); Action = (request,id) => action(request as T,id); } } private Dictionary methods; private LogikalRequest FromMessage(Type type, LogikalMessage message) { try { LogikalRequest _result = null; _result = JsonConvert.DeserializeObject(message.Payload, type) as LogikalRequest; if (_result != null) return _result; return new LogikalErrorRequest() { Status = LogikalStatus.Error, Message = $"Deserialize Failure: {message.Method}: {message.Payload}" }; } catch (Exception e) { return new LogikalErrorRequest() { Status = LogikalStatus.Error, Message = $"Exception Deserializing Request: {e.Message}\n{e.StackTrace}" }; } } public void Start() => _server.StartAsync(); public void Stop() => _server.StopAsync(); private void DoError(LogikalErrorRequest request, Guid messageID) { var _response = new LogikalErrorResponse() { Status = request.Status, Message = request.Message }; DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); } private void Connect(LogikalConnectRequest request, Guid messageID) { var _response = Server.Connect(request); DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); } private void Disconnect(LogikalDisconnectRequest request, Guid messageID) { var _response = Server.Disconnect(); DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); Disconnecting?.Invoke(this,EventArgs.Empty); } private void Login(LogikalLoginRequest request, Guid messageID) { var _response = Server.Login(request); DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); } private void Logout(LogikalLogoutRequest request, Guid messageID) { var _response = Server.Logout(); DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); } private void GetProjectCentres(LogikalProjectCentresRequest request, Guid messageID) { var _response = Server.GetProjectCentres(request); DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); } private void GetProjects(LogikalProjectsRequest request, Guid messageID) { var _response = Server.GetProjects(request); DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); } private void GetProject(LogikalProjectRequest request, Guid messageID) { var _response = Server.GetProject(request); DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); } private void GetPhases(LogikalPhasesRequest request, Guid messageID) { var _response = Server.GetPhases(request); DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); } private void GetBOM(LogikalBOMRequest request, Guid messageID) { var _response = Server.GetBillOfMaterials(request); DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); } private void GetElevationSummaries(LogikalElevationSummaryRequest request, Guid messageID) { var _response = Server.GetElevationSummaries(request); DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); } private void GetElevationDetails(LogikalElevationDetailRequest detailRequest, Guid messageID) { var _response = Server.GetElevationDetails(detailRequest); DoLog($"Server replies: {_response.ToString()}"); _server.WriteAsync(_response.ToMessage(messageID)); } public void Dispose() { if (_server != null) _ = _server.DisposeAsync().AsTask(); } } }