using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.BL;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.Core;
using Tango.Core.DI;
using Tango.Integration.Operation;
using Tango.PPC.Common.Connection;
using Tango.PPC.Common.Messages;
using Tango.PPC.Common.Models;
using Tango.PPC.Common.Navigation;
using Tango.PPC.Common.Notifications;
using Tango.PPC.Common.Printing;
using Tango.PPC.Jobs.Messages;
using Tango.PPC.UI.Dialogs;
namespace Tango.PPC.UI.Printing
{
///
/// Represents a printing manager capable of executing jobs, changing job statuses according to completion stage and generating sample and fine tuning jobs.
///
///
///
public class DefaultPrintingManager : ExtendedObject, IPrintingManager
{
private IMachineProvider _machineProvider;
private INotificationProvider _notificationProvider;
///
/// Initializes a new instance of the class.
///
/// The machine provider.
public DefaultPrintingManager(IMachineProvider machineProvider, INotificationProvider notificationProvider)
{
_machineProvider = machineProvider;
_notificationProvider = notificationProvider;
}
///
/// Prints the specified job.
/// When the job is complete the job status will change according to the completion stage.
///
/// The job.
/// The context.
///
public async Task Print(Job job, ObservablesContext context)
{
ThrowIfJobInvalid(job);
JobHandler handler = null;
#if STUBPRINT
handler = await _machineProvider.MachineOperator.PrintStub(job);
#else
try
{
handler = await _machineProvider.MachineOperator.Print(job);
}
catch (InsufficientLiquidQuantityException ex)
{
LogManager.Log(ex);
await _notificationProvider.ShowDialog(new InsufficientLiquidQuantityViewVM(ex));
throw ex;
}
#endif
handler.Completed += async (x, e) =>
{
try
{
job.JobStatus = JobStatuses.Completed;
if (!context.IsDisposed)
{
await context.SaveChangesAsync();
}
else
{
using (var newContext = ObservablesContext.CreateDefault())
{
var newJob = newContext.Jobs.SingleOrDefault(y => y.Guid == job.Guid);
if (newJob != null)
{
newJob.JobStatus = JobStatuses.Completed;
await newContext.SaveChangesAsync();
}
}
}
RaiseJobSaved(job);
}
catch (Exception ex)
{
LogManager.Log(ex, "Error occurred after job printing completed.");
}
};
handler.Canceled += (x, e) =>
{
try
{
//No change in status !
//await context.SaveChangesAsync();
RaiseJobSaved(job);
}
catch (Exception ex)
{
LogManager.Log(ex, "Error occurred after job printing completed.");
}
};
handler.Failed += async (x, e) =>
{
try
{
job.JobStatus = JobStatuses.Disrupted;
if (!context.IsDisposed)
{
await context.SaveChangesAsync();
}
else
{
using (var newContext = ObservablesContext.CreateDefault())
{
var newJob = newContext.Jobs.SingleOrDefault(y => y.Guid == job.Guid);
if (newJob != null)
{
newJob.JobStatus = JobStatuses.Disrupted;
await newContext.SaveChangesAsync();
}
}
}
RaiseJobSaved(job);
}
catch (Exception ex)
{
LogManager.Log(ex, "Error occurred after job printing completed.");
}
};
return handler;
}
///
/// Creates a sample dye job from the specified job and prints it.
/// When the sample dye job is complete, the job sample dye status will change.
///
/// The job.
/// The context.
///
public async Task PrintSample(Job job, ObservablesContext context)
{
ThrowIfJobInvalid(job);
LogManager.Log("Cloning job...");
Job sampleDyeJob = job.Clone();
sampleDyeJob.Guid = job.Guid;
sampleDyeJob.Designation = BL.Enumerations.JobDesignations.SampleDye;
sampleDyeJob.Name = job.Name;
if (job.JobType == BL.Enumerations.JobTypes.Embroidery)
{
sampleDyeJob.NumberOfUnits = job.SampleUnitsOrMeters;
}
else
{
sampleDyeJob.NumberOfUnits = 1;
foreach (var segment in sampleDyeJob.OrderedSegments)
{
segment.Length = job.SampleUnitsOrMeters;
}
}
context.SaveChanges();
RaiseJobSaved(job);
LogManager.Log("Executing sample dye job...");
var handler = await _machineProvider.MachineOperator.Print(sampleDyeJob);
handler.Completed += async (x, e) =>
{
try
{
job.JobEditingState = BL.Enumerations.EditingStates.SampleDye;
job.JobSampleDyeStatus = BL.Enumerations.SampleDyeStatuses.PendingApproval;
await context.SaveChangesAsync();
}
catch (Exception ex)
{
LogManager.Log(ex, "Error occurred after sample dye printing completed.");
}
};
return handler;
}
///
/// Creates a fine tuning job from the specified job and fine tune items.
/// When the fine tuning job is complete, the job fine tuning status will change.
///
/// The job.
/// The context.
/// The fine tune items.
///
public async Task PrintFineTuning(Job job, ObservablesContext context, IEnumerable fineTuneItems)
{
ThrowIfJobInvalid(job);
LogManager.Log("Cloning job...");
Job fineTuneJob = job.Clone();
fineTuneJob.NumberOfUnits = 1;
fineTuneJob.Designation = BL.Enumerations.JobDesignations.FineTuning;
fineTuneJob.Guid = job.Guid;
fineTuneJob.Name = job.Name;
fineTuneJob.Segments.Clear();
foreach (var suggestion in fineTuneItems.Where(x => x.IsSelected).SelectMany(x => x.Suggestions))
{
var segment = fineTuneJob.AddSolidSegment(suggestion.Color);
}
var handler = await _machineProvider.MachineOperator.Print(fineTuneJob);
handler.Completed += async (x, e) =>
{
try
{
job.JobEditingState = BL.Enumerations.EditingStates.FineTuning;
job.JobFineTuningStatus = BL.Enumerations.FineTuningStatuses.PendingApproval;
await context.SaveChangesAsync();
}
catch (Exception ex)
{
LogManager.Log(ex, "Error occurred after fine tunning job completed.");
}
};
return handler;
}
///
/// Raises the job saved messenger message.
///
/// The job.
private void RaiseJobSaved(Job job)
{
TangoMessenger.Default.Send(new JobSavedMessage() { Job = job });
}
private void ThrowIfJobInvalid(Job job)
{
if (job.Segments.SelectMany(x => x.BrushStops).Any(x => x.IsOutOfGamut))
{
throw new InvalidOperationException("Error starting job. Color is out of range.");
}
if (job.Segments.SelectMany(x => x.BrushStops).Any(x => x.BrushColorSpace == ColorSpaces.Catalog && x.ColorCatalogsItem == null))
{
throw new InvalidOperationException("Error starting job. Please select a catalog color.");
}
if (job.Rml.Cct == null)
{
throw new InvalidOperationException($"Error starting job. No color table found for thread '{job.Rml.Name}'.");
}
}
}
}