using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Tango.BL;
using Tango.BL.Builders;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.Core.Commands;
using Tango.CSV;
using Tango.MachineStudio.Common.Notifications;
using Tango.MachineStudio.HardwareDesigner.Comparison;
using Tango.MachineStudio.HardwareDesigner.Report;
using Tango.SharedUI;
namespace Tango.MachineStudio.HardwareDesigner.ViewModels
{
///
/// class ComparisonWizardViewVM is view model of dialog for compare properties of 2 hardware versions
///
///
public class ComparisonWizardViewVM : DialogViewVM
{
private INotificationProvider _notification;
#region Properties
private ObservableCollection _hardwareVersions;
///
/// Gets or sets the hardware versions. Contains all available versions.
///
///
/// The hardware versions.
///
public ObservableCollection HardwareVersions
{
get { return _hardwareVersions; }
set { _hardwareVersions = value; RaisePropertyChangedAuto(); }
}
private HardwareVersion _selectedVersion1;
///
/// Gets or sets the selected version1 contains selected value from left combo box
///
///
/// The selected version1.
///
public HardwareVersion SelectedVersion1
{
get { return _selectedVersion1; }
set
{
if (value != null && (_selectedVersion1 == null || _selectedVersion1.Guid != value.Guid))
{
_selectedVersion1 = value;
RaisePropertyChangedAuto();
OnSelectedVersionChanged();
}
}
}
private HardwareVersion _selectedVersion2;
///
/// Gets or sets the selected version2 contains selected value from right combo box
///
///
/// The selected version2.
///
public HardwareVersion SelectedVersion2
{
get { return _selectedVersion2; }
set
{
if (value != null && (_selectedVersion2 == null || _selectedVersion2.Guid != value.Guid))
{
_selectedVersion2 = value;
RaisePropertyChangedAuto();
OnSelectedVersionChanged();
}
}
}
private bool _isShowDifference;
///
/// Gets or sets a value indicating whether this instance is show difference. Binding to value of checkbox in GUI.
///
///
/// true if this instance is show difference; otherwise, false.
///
public bool IsShowDifference
{
get { return _isShowDifference; }
set
{
_isShowDifference = value;
RaisePropertyChangedAuto();
}
}
private HardwareCompareResult _result;
///
/// Gets or sets the result. Contains result of the comparison properties from selected versions.
///
///
/// The result.
///
public HardwareCompareResult Result
{
get
{
return _result;
}
set
{
_result = value;
RaisePropertyChangedAuto();
InvalidateRelayCommands();
}
}
private bool _isRunning;
public bool IsRunning
{
get { return _isRunning; }
set { _isRunning = value; RaisePropertyChangedAuto(); }
}
#endregion properties
#region Command
public RelayCommand GenerateReportCommand { get; set; }
#endregion
#region Constructors
public ComparisonWizardViewVM(IEnumerable availableVersions, HardwareVersion selectedVersion, INotificationProvider notification)
{
HardwareVersions = new ObservableCollection(availableVersions);
_selectedVersion1 = selectedVersion;
_isShowDifference = false;
IsRunning = false;
IsShowDifference = true;
_notification = notification;
GenerateReportCommand = new RelayCommand(GenerateReport, () => Result != null);
}
#endregion
#region Report
///
/// Generates the report. Save properties in .csv file in format Collection name/Component name/Property name/Value1 of version1/Value2 of version 2
///
private void GenerateReport()
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.Title = "Save Report";
dlg.Filter = "CSV Files|*.csv";
dlg.FileName = $"hw_compare_report__{SelectedVersion1.Name}__vs__{SelectedVersion2.Name}";
dlg.DefaultExt = ".csv";
if (dlg.ShowDialog().Value)
{
try
{
CsvFile csvFile = new CsvFile(new CsvDestination(dlg.FileName), new CsvDefinition()
{
Columns = new List()
{
"Collection",
"Component",
"Property",
SelectedVersion1.Name,
SelectedVersion2.Name,
},
});
foreach (var collection in Result.Collections.Where(x => x.HasDifferences || !IsShowDifference))
{
ReportModel model_collection = new ReportModel();
model_collection.Collection = collection.CollectionName;
csvFile.Append(model_collection);
foreach (var component in collection.Components.Where(x => x.HasDifferences || !IsShowDifference))
{
ReportModel model_component = new ReportModel();
model_component.Component = component.ComponentName;
csvFile.Append(model_component);
foreach (var prop in component.Properties.Where(x => x.HasDifferences || !IsShowDifference))
{
ReportModel model = new ReportModel();
model.Property = prop.PropertyName;
model.HW_1 = prop.Value1;
model.HW_2 = prop.Value2;
csvFile.Append(model);
}
}
}
csvFile.Dispose();
_notification.ShowInfo("Report generated successfully.");
}
catch (Exception ex)
{
LogManager.Log(ex, "Error generating HW version comparison report.");
_notification.ShowError($"Error generating HW version comparison report.\n{ex.Message}");
}
}
}
#endregion
#region Selected Version Changed
private async void OnSelectedVersionChanged()
{
if (SelectedVersion1 != null && SelectedVersion2 != null)
{
IsRunning = true;
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
var h1 = await new HardwareVersionBuilder(db).Set(SelectedVersion1.Guid).WithHardwareComponents().BuildAsync();
var h2 = await new HardwareVersionBuilder(db).Set(SelectedVersion2.Guid).WithHardwareComponents().BuildAsync();
await Task.Factory.StartNew(() =>
{
Result = CompareHardwareVersions(h1, h2);
IsRunning = false;
});
}
}
}
#endregion
#region Compare Versions
private HardwareCompareResult CompareHardwareVersions(HardwareVersion h1, HardwareVersion h2)
{
_result = new HardwareCompareResult();
_result.Collections.Add(CompareMotorsCollection(h1, h2));
_result.Collections.Add(CompareDancerCollection(h1, h2));
_result.Collections.Add(ComparePidControlsCollection(h1, h2));
_result.Collections.Add(CompareWindersCollection(h1, h2));
_result.Collections.Add(CompareSpeedSensorsCollection(h1, h2));
_result.Collections.Add(CompareBlowersCollection(h1, h2));
_result.Collections.Add(CompareBreakSensorCollection(h1, h2));
return _result;
}
private HardwareComponentCollectionCompareResult CompareMotorsCollection(HardwareVersion h1, HardwareVersion h2)
{
HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult()
{
CollectionName = "MOTORS"
};
foreach (var motorTypeCode in Enum.GetValues(typeof(HardwareMotorTypes)).Cast())
{
var motor1 = h1.HardwareMotors.SingleOrDefault(x => x.HardwareMotorType.Code == motorTypeCode.ToInt32());
var motor2 = h2.HardwareMotors.SingleOrDefault(x => x.HardwareMotorType.Code == motorTypeCode.ToInt32());
var componentResult = CompareComponents(
motorTypeCode.ToDescription(),
GetComponentProperties(typeof(HardwareMotorBase)),
motor1,
motor2);
collection.Components.Add(componentResult);
}
collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection();
return collection;
}
private HardwareComponentCollectionCompareResult CompareDancerCollection(HardwareVersion h1, HardwareVersion h2)
{
HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult()
{
CollectionName = "DANCERS"
};
foreach (var dancerTypeCode in Enum.GetValues(typeof(HardwareDancerTypes)).Cast())
{
var motor1 = h1.HardwareDancers.SingleOrDefault(x => x.HardwareDancerType.Code == dancerTypeCode.ToInt32());
var motor2 = h2.HardwareDancers.SingleOrDefault(x => x.HardwareDancerType.Code == dancerTypeCode.ToInt32());
var componentResult = CompareComponents(
dancerTypeCode.ToDescription(),
GetComponentProperties(typeof(HardwareDancerBase)),
motor1,
motor2);
collection.Components.Add(componentResult);
}
collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection();
return collection;
}
private HardwareComponentCollectionCompareResult ComparePidControlsCollection(HardwareVersion h1, HardwareVersion h2)
{
HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult()
{
CollectionName = "PID CONTROLS"
};
foreach (var pidControlsTypeCode in Enum.GetValues(typeof(HardwarePidControlTypes)).Cast())
{
var motor1 = h1.HardwarePidControls.SingleOrDefault(x => x.HardwarePidControlType.Code == pidControlsTypeCode.ToInt32());
var motor2 = h2.HardwarePidControls.SingleOrDefault(x => x.HardwarePidControlType.Code == pidControlsTypeCode.ToInt32());
var componentResult = CompareComponents(
pidControlsTypeCode.ToDescription(),
GetComponentProperties(typeof(HardwarePidControlBase)),
motor1,
motor2);
collection.Components.Add(componentResult);
}
collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection();
return collection;
}
private HardwareComponentCollectionCompareResult CompareWindersCollection(HardwareVersion h1, HardwareVersion h2)
{
HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult()
{
CollectionName = "WINDERS"
};
foreach (var WinderTypeCode in Enum.GetValues(typeof(HardwareWinderTypes)).Cast())
{
var motor1 = h1.HardwareWinders.SingleOrDefault(x => x.HardwareWinderType.Code == WinderTypeCode.ToInt32());
var motor2 = h2.HardwareWinders.SingleOrDefault(x => x.HardwareWinderType.Code == WinderTypeCode.ToInt32());
var componentResult = CompareComponents(
WinderTypeCode.ToDescription(),
GetComponentProperties(typeof(HardwareWinderBase)),
motor1,
motor2);
collection.Components.Add(componentResult);
}
collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection();
return collection;
}
private HardwareComponentCollectionCompareResult CompareSpeedSensorsCollection(HardwareVersion h1, HardwareVersion h2)
{
HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult()
{
CollectionName = "SPEED SENSORS"
};
foreach (var speedSewnsorsTypeCode in Enum.GetValues(typeof(HardwareSpeedSensorTypes)).Cast())
{
var motor1 = h1.HardwareSpeedSensors.SingleOrDefault(x => x.HardwareSpeedSensorType.Code == speedSewnsorsTypeCode.ToInt32());
var motor2 = h2.HardwareSpeedSensors.SingleOrDefault(x => x.HardwareSpeedSensorType.Code == speedSewnsorsTypeCode.ToInt32());
var componentResult = CompareComponents(
speedSewnsorsTypeCode.ToDescription(),
GetComponentProperties(typeof(HardwareSpeedSensorBase)),
motor1,
motor2);
collection.Components.Add(componentResult);
}
collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection();
return collection;
}
private HardwareComponentCollectionCompareResult CompareBlowersCollection(HardwareVersion h1, HardwareVersion h2)
{
HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult()
{
CollectionName = "BLOWERS"
};
foreach (var blowersTypeCode in Enum.GetValues(typeof(HardwareBlowerTypes)).Cast())
{
var motor1 = h1.HardwareBlowers.SingleOrDefault(x => x.HardwareBlowerType.Code == blowersTypeCode.ToInt32());
var motor2 = h2.HardwareBlowers.SingleOrDefault(x => x.HardwareBlowerType.Code == blowersTypeCode.ToInt32());
var componentResult = CompareComponents(
blowersTypeCode.ToDescription(),
GetComponentProperties(typeof(HardwareBlowerBase)),
motor1,
motor2);
collection.Components.Add(componentResult);
}
collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection();
return collection;
}
private HardwareComponentCollectionCompareResult CompareBreakSensorCollection(HardwareVersion h1, HardwareVersion h2)
{
HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult()
{
CollectionName = "BREAK SENSOR"
};
foreach (var breakSewnsorsTypeCode in Enum.GetValues(typeof(HardwareBreakSensorTypes)).Cast())
{
var motor1 = h1.HardwareBreakSensors.SingleOrDefault(x => x.HardwareBreakSensorType.Code == breakSewnsorsTypeCode.ToInt32());
var motor2 = h2.HardwareBreakSensors.SingleOrDefault(x => x.HardwareBreakSensorType.Code == breakSewnsorsTypeCode.ToInt32());
var componentResult = CompareComponents(
breakSewnsorsTypeCode.ToDescription(),
GetComponentProperties(typeof(HardwareBreakSensorBase)),
motor1,
motor2);
collection.Components.Add(componentResult);
}
collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection();
return collection;
}
private HardwareComponentCompareResult CompareComponents(String name, List properties, Object component1, Object component2)
{
HardwareComponentCompareResult result = new HardwareComponentCompareResult();
result.ComponentName = name;
result.HasComponent1 = component1 != null;
result.HasComponent2 = component2 != null;
foreach (var prop in properties)
{
var hProp = new HardwareComponentPropertyResult();
hProp.PropertyName = prop.Name;
hProp.Value1 = component1 != null ? (prop.GetValue(component1) == null ? "" : prop.GetValue(component1).ToString()) : null;
hProp.Value2 = component2 != null ? (prop.GetValue(component2) == null ? "" : prop.GetValue(component2).ToString()) : null;
result.Properties.Add(hProp);
}
return result;
}
private List GetComponentProperties(Type componentType)
{
List exclude = new List()
{
"Guid",
"ID",
"LastUpdated",
"Parameters",
};
return componentType.GetProperties(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public).Where(x => !x.PropertyType.IsClass && !exclude.Contains(x.Name)).ToList();
}
#endregion
}
}