using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.BL;
using Tango.BL.DTO;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.Core;
using Tango.Core.DI;
using Tango.Integration.ExternalBridge;
using Tango.Integration.JobRuns;
using Tango.PPC.Common.Connection;
using Tango.PPC.Common.ExternalBridge;
using Tango.PPC.Shared.Statistics;
namespace Tango.PPC.Common.Statistics
{
[TangoCreateWhenRegistered]
public class DefaultStatisticsService : ExtendedObject, IStatisticsService, IExternalBridgeRequestHandler
{
private IMachineProvider _machineProvider;
private Dictionary<ExternalBridgeReceiver, String> _streamingReceivers;
private List<ColorCatalog> _catalogs;
private List<ColorCatalogsItem> _color_catalog_Items;
private List<ColorSpace> _colorSpaces;
private Dictionary<String, LiquidType> _liquidTypes;
public bool Enabled { get; set; } = true;
public DefaultStatisticsService(IPPCExternalBridgeService externalBridge, IMachineProvider machineProvider)
{
_streamingReceivers = new Dictionary<ExternalBridgeReceiver, string>();
try
{
_machineProvider = machineProvider;
externalBridge.RegisterRequestHandler(this);
}
catch (Exception ex)
{
LogManager.Log(ex, "Error initializing the statistics service.");
Enabled = false;
}
_machineProvider.MachineOperator.JobRunsLogger.JobRunAvailable += JobRunsLogger_JobRunAvailable;
}
private void JobRunsLogger_JobRunAvailable(object sender, JobRunAvailableEventArgs e)
{
Task.Factory.StartNew(async () =>
{
var jobRunComposition = await CreateJobRunComposition(e.JobRun);
foreach (var receiver in _streamingReceivers.ToList())
{
try
{
var response = new StartJobRunsStreamingResponse();
response.JobRunComposition = jobRunComposition;
await receiver.Key.SendGenericResponse(response, receiver.Value);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
});
}
[ExternalBridgeRequestHandlerMethod(typeof(GetStatisticsRequiredFiltersRequest), RequestHandlerLoggingMode.LogRequestName)]
public async Task OnGetStatisticsRequiredFiltersRequest(GetStatisticsRequiredFiltersRequest request, String token, ExternalBridgeReceiver receiver)
{
this.ThrowIfDisabled();
var response = new GetStatisticsRequiredFiltersResponse();
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
var jobNames = (await db.JobRuns.Select(x => x.JobName).ToListAsync()).Distinct().ToList();
var threadNames = await db.Rmls.Select(x => new { x.Guid, x.Name, x.DisplayName }).ToListAsync();
if (_machineProvider.Machine.SiteGuid != null)
{
var siteRmlsGuids = (await db.SitesRmls.Where(x => x.SiteGuid == _machineProvider.Machine.SiteGuid).ToListAsync()).Select(x => x.RmlGuid).Where(x => x != null).Distinct().ToList();
threadNames.RemoveAll(x => !siteRmlsGuids.Contains(x.Guid));
}
response.FiltersData.Jobs = jobNames;
response.FiltersData.Rmls = threadNames.Select(x => new ThreadFilterData() { Guid = x.Guid, Name = x.DisplayName.IsNotNullOrEmpty() ? x.DisplayName : x.Name }).ToList();
}
await receiver.SendGenericResponse(response, token);
}
[ExternalBridgeRequestHandlerMethod(typeof(GetStatisticsRequest), RequestHandlerLoggingMode.LogRequestName)]
public async Task OnGetStatisticsRequest(GetStatisticsRequest request, String token, ExternalBridgeReceiver receiver)
{
this.ThrowIfDisabled();
var response = new GetStatisticsResponse();
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
response.Result.LiquidTypes = db.LiquidTypes.ToList().Select(x => LiquidTypeDTO.FromObservable(x)).ToList();
var filters = request.Filters;
var db_JobRuns = db.JobRuns.Where(x => (x.StartDate <= filters.EndDateUTC && x.StartDate >= filters.StartDateUTC));
int[] jobRunStatusArr = filters.EndStatuses.Distinct().ToArray();
if (jobRunStatusArr.Length > 0)
{
db_JobRuns = db_JobRuns.Where(x => jobRunStatusArr.Contains(x.Status));
}
int[] jobDesignationArr = filters.JobDesignation.Distinct().ToArray();
if (jobDesignationArr.Length > 0)
{
db_JobRuns = db_JobRuns.Where(x => jobDesignationArr.Contains(x.JobDesignation));
}
if (!filters.IncludeHeadCleaning)
{
db_JobRuns = db_JobRuns.Where(x => !x.IsHeadCleaning);
}
List<String> rmlGuids = filters.RmlGuids;
if (filters.RmlGuids.Count > 0)
{
db_JobRuns = db_JobRuns.Where(x => rmlGuids.Contains(x.RmlGuid));
}
if (filters.JobName.IsNotNullOrEmpty())
{
if (!filters.ExactJobName)
{
db_JobRuns = db_JobRuns.Where(x => x.JobName.ToLower().StartsWith(filters.JobName.ToLower()));
}
else
{
db_JobRuns = db_JobRuns.Where(x => x.JobName.ToLower() == filters.JobName.ToLower());
}
}
db_JobRuns = db_JobRuns.Where(x => x.JobLength >= filters.MinLength && x.JobLength <= filters.MaxLength);
var jobRuns = await db_JobRuns.ToListAsync();
foreach (var jobRun in jobRuns)
{
JobRunComposition jobRunComposition = await CreateJobRunComposition(jobRun);
response.Result.JobRuns.Add(jobRunComposition);
}
}
await receiver.SendGenericResponse(response, token);
}
private async Task<JobRunComposition> CreateJobRunComposition(JobRun jobRun)
{
if (_colorSpaces == null)
{
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
_colorSpaces = await db.ColorSpaces.ToListAsync();
_catalogs = await db.ColorCatalogs.ToListAsync();
_color_catalog_Items = await db.ColorCatalogsItems.ToListAsync();
}
}
if (_liquidTypes == null)
{
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
var types = await db.LiquidTypes.ToListAsync();
_liquidTypes = new Dictionary<string, LiquidType>();
foreach (var t in types)
{
_liquidTypes.Add(t.Name, t);
}
}
}
JobRunComposition jobRunComposition = new JobRunComposition();
jobRunComposition.JobRun = JobRunDTO.FromObservable(jobRun);
PresentationJob pj = new PresentationJob();
pj.ID = jobRun.ID;
jobRunComposition.Job = pj;
if (jobRun.JobFile != null)
{
foreach (var segment in jobRun.JobFile.Segments)
{
PresentationSegment ps = new PresentationSegment();
ps.Length = (int)segment.Length;
pj.Segments.Add(ps);
foreach (var stop in segment.BrushStops.OrderBy(x => x.StopIndex).DistinctBy(x => x.OffsetPercent).ToList())
{
PresentationBrushStop pbs = new PresentationBrushStop();
pbs.ColorSpace = _colorSpaces.First(x => x.Guid == stop.ColorSpaceGuid).Space;
pbs.StartMeters = segment.Length * (stop.OffsetPercent / 100d); ;
foreach (var liquidType in stop.LiquidVolumes)
{
PresentationLiquidVolume plt = new PresentationLiquidVolume();
if (_liquidTypes.ContainsKey(liquidType.LiquidTypeName))
{
plt.LiquidType = _liquidTypes[liquidType.LiquidTypeName];
plt.Volume = liquidType.Volume;
pbs.LiquidVolumes.Add(plt);
}
}
pbs.LiquidVolumes = pbs.LiquidVolumes.OrderBy(x => x.LiquidType.PreferredIndex).ToList();
switch (pbs.ColorSpace)
{
case ColorSpaces.RGB:
pbs.Red = stop.Red;
pbs.Green = stop.Green;
pbs.Blue = stop.Blue;
break;
case ColorSpaces.LAB:
pbs.L = stop.L;
pbs.A = stop.A;
pbs.B = stop.B;
break;
case ColorSpaces.Volume:
//foreach (var lightInk in pbs.LiquidVolumes.Where(x => x.LiquidType.IsLightInk && x.Volume > 0))
//{
// var darkInk = pbs.LiquidVolumes.FirstOrDefault(x => x.LiquidType.Code == lightInk.LiquidType.DarkInkCode);
// if (darkInk != null)
// {
// darkInk.Volume = (double)((decimal)lightInk.Volume / 10m);
// lightInk.Volume = 0;
// }
//}
break;
case ColorSpaces.Catalog:
pbs.Catalog = _catalogs.FirstOrDefault(x => x.Guid == stop.ColorCatalogGuid)?.Name;
pbs.CatalogItem = _color_catalog_Items.FirstOrDefault(x => x.Guid == stop.ColorCatalogItemGuid)?.Name;
break;
}
pbs.BestMatchR = stop.BestMatchR;
pbs.BestMatchG = stop.BestMatchG;
pbs.BestMatchB = stop.BestMatchB;
ps.Stops.Add(pbs);
}
}
}
jobRunComposition.JobRun.JobString = null;
jobRunComposition.JobRun.LiquidQuantityString = null;
return jobRunComposition;
}
[ExternalBridgeRequestHandlerMethod(typeof(GetJobRunExtendedInfoRequest), RequestHandlerLoggingMode.LogRequestName)]
public async Task OnGetJobRunExtendedInfoRequest(GetJobRunExtendedInfoRequest request, String token, ExternalBridgeReceiver receiver)
{
this.ThrowIfDisabled();
var response = new GetJobRunExtendedInfoResponse();
String filePath = Path.Combine((_machineProvider.MachineOperator.JobRunsLogger as BasicJobRunsLogger).JobRunsFolder, $"{request.JobRunID}.run");
String json = File.ReadAllText(filePath);
JobRunInfo info = JsonConvert.DeserializeObject<JobRunInfo>(json);
response.ExtendedInfo.JobRunID = info.JobRunID;
response.ExtendedInfo.JobTicket = info.JobTicket;
response.ExtendedInfo.Events = info.Events;
response.ExtendedInfo.StartMachineStatus = info.StartMachineStatus;
response.ExtendedInfo.EndMachineStatus = info.EndMachineStatus;
await receiver.SendGenericResponse(response, token);
}
[ExternalBridgeRequestHandlerMethod(typeof(StartJobRunsStreamingRequest), RequestHandlerLoggingMode.LogRequestName)]
public async Task OnStartJobRunsStreamingRequest(StartJobRunsStreamingRequest request, String token, ExternalBridgeReceiver receiver)
{
this.ThrowIfDisabled();
if (!_streamingReceivers.ContainsKey(receiver))
{
_streamingReceivers.Add(receiver, token);
}
var response = new StartJobRunsStreamingResponse();
await receiver.SendGenericResponse(response, token);
}
[ExternalBridgeRequestHandlerMethod(typeof(StopJobRunsStreamingRequest), RequestHandlerLoggingMode.LogRequestName)]
public async Task OnStopJobRunsStreamingRequest(StopJobRunsStreamingRequest request, String token, ExternalBridgeReceiver receiver)
{
this.ThrowIfDisabled();
if (_streamingReceivers.ContainsKey(receiver))
{
_streamingReceivers.Remove(receiver);
}
var response = new StopJobRunsStreamingResponse();
await receiver.SendGenericResponse(response, token);
}
public void OnReceiverDisconnected(ExternalBridgeReceiver receiver)
{
if (_streamingReceivers.ContainsKey(receiver))
{
_streamingReceivers.Remove(receiver);
}
}
}
}