using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Threading; using System.Windows; using System.Windows.Forms.Design; using System.Windows.Media.Imaging; using InABox.Core; using InABox.Scripting; using InABox.WPF; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.Win32; namespace InABox.DynamicGrid { public delegate bool OnImportItem(object o); public class CustomiseImportArgs { public string FileName { get; set; } } public delegate void OnCustomiseImport(object sender, CustomiseImportArgs e); public class DynamicImportGrid : DynamicDataGrid { private static readonly BitmapImage run = Wpf.Resources.rightarrow.AsBitmapImage(); private DynamicImageColumn ImportColumn; private bool _canImport = true; public bool CanImport { get => _canImport; set { if(_canImport != value) { _canImport = value; ImportColumn.Position = _canImport ? DynamicActionColumnPosition.End : DynamicActionColumnPosition.Hidden; Refresh(true, false); } } } protected override void Init() { base.Init(); ImportColumn = new DynamicImageColumn(ImportImage, ImportAction); ActionColumns.Add(ImportColumn); HiddenColumns.Add(x => x.EntityName); HiddenColumns.Add(x => x.ImporterDescription); HiddenColumns.Add(x => x.FileName); HiddenColumns.Add(x => x.Definition); HiddenColumns.Add(x => x.HasHeader); HiddenColumns.Add(x => x.HeaderRows); HiddenColumns.Add(x => x.ColumnWidths); HiddenColumns.Add(x => x.Script); HiddenColumns.Add(x => x.Settings); } protected override void DoReconfigure(DynamicGridOptions options) { base.DoReconfigure(options); options.RecordCount = true; options.ShowHelp = true; } public Type EntityType { get; set; } public Guid EntityID { get; set; } public event OnImportItem OnImportItem; public event OnCustomiseImport OnCustomiseImport; public event ImportSaveEvent OnSave; public event ImportLoadEvent OnLoad; protected override void ShowHelp(string slug) { base.ShowHelp("Import_Data"); } private BitmapImage? ImportImage(CoreRow? arg) { return arg != null ? run : null; } public static bool CreateImporter(Importer importer, [NotNullWhen(true)] ref string? filename, [NotNullWhen(true)] out IImporter? iimporter, Action? customiseImport = null, Func? onImport = null) { iimporter = null; var definition = ImportFactory.Definitions.FirstOrDefault(x => x.Description.Equals(importer.ImporterDescription)); var entityType = CoreUtils.GetEntity(importer.EntityName); if (definition != null) { ScriptDocument? helper = null; try { if (!importer.Script.IsNullOrWhiteSpace()) { helper = new ScriptDocument(importer.Script); if (!helper.Compile()) { MessageBox.Show("Unable to Compile Import Helper Script!"); return false; } } } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } if(filename is null) { var fullFileName = importer.FileName; var path = Path.GetDirectoryName(fullFileName); var extension = Path.GetExtension(fullFileName); var args = new CustomiseImportArgs { FileName = Path.GetFileNameWithoutExtension(fullFileName) }; customiseImport?.Invoke(args); var filename2 = CoreUtils.SanitiseFileName(args.FileName); var dlg = new OpenFileDialog { Filter = definition.Filter, FileName = Path.Combine(path, filename2) + (extension.StartsWith(".") ? "" : ".") + extension }; if (!string.IsNullOrWhiteSpace(dlg.FileName) && Directory.Exists(Path.GetDirectoryName(dlg.FileName))) dlg.InitialDirectory = Path.GetDirectoryName(dlg.FileName); if(dlg.ShowDialog() == true) { filename = dlg.FileName; } else { return false; } } else { var path = Path.GetDirectoryName(filename); var extension = Path.GetExtension(filename); var args = new CustomiseImportArgs { FileName = Path.GetFileNameWithoutExtension(filename) }; customiseImport?.Invoke(args); var filename2 = CoreUtils.SanitiseFileName(args.FileName); filename = Path.ChangeExtension(Path.Combine(path, filename2), extension); } iimporter = ImportFactory.Create(definition, entityType, importer); iimporter.BeforeProcess += (sender, values) => { if (helper != null) return helper.Execute("Module", "BeforeProcess", new object[] { values }); return true; }; iimporter.AfterProcess += (sender, item, values) => { var bOK = true; if (helper != null) bOK = helper.Execute("Module", "AfterProcess", new[] { item, values }); bOK = !bOK || onImport is null || onImport.Invoke(item); return bOK; }; var mappingDefinitions = importer.Definition; var mappings = Serialization.Deserialize>(mappingDefinitions); iimporter.Mappings.AddRange(mappings); return true; } else { return false; } } private bool ImportAction(CoreRow? arg) { if (arg != null) { var importer = arg.ToObject(); string? filename = null; if (CreateImporter(importer, ref filename, out var iimporter, (args) => OnCustomiseImport?.Invoke(this, args), (o) => OnImportItem?.Invoke(o) != false)) { iimporter.OnLoad += OnLoad; iimporter.OnSave += OnSave; Progress.Show("Importing Data"); using var stream = new FileStream(filename, FileMode.Open, FileAccess.Read); Progress.SetMessage("Opening File"); if (iimporter.Open(stream)) { if (iimporter.ReadHeader()) { var mismatches = iimporter.Mappings.Where(x => !string.IsNullOrWhiteSpace(x.Field) && !iimporter.Fields.Contains(x.Field) ).Select(x => x.Field).ToArray(); if (!mismatches.Any()) { var imported = iimporter.Import(); Progress.Close(); MessageBox.Show(string.Format("Imported {0} records!", imported)); var LogFile = Path.ChangeExtension(filename, ".log"); File.AppendAllLines(LogFile, iimporter.Log.ToArray()); Process.Start(new ProcessStartInfo(LogFile) { UseShellExecute = true }); } else { Progress.Close(); MessageBox.Show("Import Mappings do not match file headers!\n\n- " + string.Join("\n- ", mismatches), "Import Failed"); } } else { Progress.Close(); MessageBox.Show("Unable to Read Headers from {0}", Path.GetFileName(filename)); } } else { Progress.Close(); MessageBox.Show("Unable to Open {0}", Path.GetFileName(filename)); } iimporter.Close(); } } return false; } private bool Importer_BeforeProcess(object sender, Dictionary values) { return true; //throw new NotImplementedException(); } protected override void Reload( Filters criteria, Columns columns, ref SortOrder? sort, CancellationToken token, Action action) { criteria.Add(new Filter(x => x.EntityName).IsEqualTo(EntityType.EntityName())); if (EntityID != Guid.Empty) criteria.Add(new Filter(x => x.EntityID).IsEqualTo(EntityID)); base.Reload(criteria, columns, ref sort, token, action); } public override Importer CreateItem() { var result = base.CreateItem(); result.EntityName = EntityType.EntityName(); result.EntityID = EntityID; return result; } public override bool EditItems(Importer[] items, Func? PageDataHandler = null, bool PreloadPages = false) { if (items.Length != 1) { MessageBox.Show("Please select a single item to edit!"); return false; } var form = new DynamicImportForm(items[0]); if (form.ShowDialog() == true) { SaveItem(items[0]); return true; } return false; } } }