private void TransferData(EntityCollection ec, IOrganizationService service)
        {
            // References to websites
            var webSitesRefId = ec.Entities.SelectMany(e => e.Attributes)
                                .Where(a => a.Value is EntityReference reference && reference.LogicalName == "adx_website")
                                .Select(a => ((EntityReference)a.Value).Id)
                                .Distinct()
                                .ToList();

            // Websites included in records to process
            var webSitesIds = ec.Entities.Where(e => e.LogicalName == "adx_website")
                              .Select(e => e.Id)
                              .ToList();

            // If some references are not found in websites included in records
            // to process, ask the user to map to the appropriate website
            if (!webSitesRefId.All(id => webSitesIds.Contains(id)))
            {
                try
                {
                    var targetWebSites = service.RetrieveMultiple(new QueryExpression("adx_website")
                    {
                        ColumnSet = new ColumnSet("adx_name")
                    }).Entities;

                    if (!webSitesRefId.All(id => targetWebSites.Select(w => w.Id).Contains(id)))
                    {
                        var wsmDialog = new WebSiteMapper(ec, targetWebSites.Select(t => new Website(t)).ToList());
                        if (wsmDialog.ShowDialog() == DialogResult.Cancel)
                        {
                            return;
                        }
                    }
                }
                catch (FaultException <OrganizationServiceFault> error)
                {
                    if (error.Detail.ErrorCode == -2147217150)
                    {
                        MessageBox.Show(this,
                                        @"The target environment does not seem to have Portals solutions installed!",
                                        @"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    else
                    {
                        MessageBox.Show(this,
                                        $@"An unknown error occured when searching for websites: {error.Detail.Message}",
                                        @"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    pnlImport.SendToBack();
                    tsMain.Enabled = true;
                    return;
                }
            }

            var pluginCheck     = ec.Entities.Any(e => e.LogicalName == "adx_webpage");
            var javascriptCheck =
                ec.Entities.Any(e =>
                                e.LogicalName == "annotation" &&
                                (e.GetAttributeValue <string>("filename")?.ToLower().EndsWith(".js") ?? false)) &&
                nManager.HasJsRestriction;
            var webFileCleaning = ec.Entities.Any(e =>
                                                  e.LogicalName == "annotation" &&
                                                  e.GetAttributeValue <EntityReference>("objectid")?.LogicalName == "adx_webfile");

            if (pluginCheck || javascriptCheck)
            {
                var dialog = new PreImportWarningDialog(pluginCheck, javascriptCheck, webFileCleaning);
                var result = dialog.ShowDialog(this);
                if (result == DialogResult.Cancel)
                {
                    return;
                }

                iSettings.DeactivateWebPagePlugins        = true;
                iSettings.RemoveJavaScriptFileRestriction = true;
                iSettings.CleanWebFiles = dialog.CleanWebFiles;
            }

            var lm = new LogManager(GetType());

            if (File.Exists(lm.FilePath))
            {
                if (MessageBox.Show(this, @"A log file already exists. Would you like to create a new log file?", @"Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    File.Copy(lm.FilePath, $"{lm.FilePath.Substring(0, lm.FilePath.Length - 4)}-{DateTime.Now:yyyyMMdd_HHmmss}.txt", true);
                    File.Delete(lm.FilePath);
                }
            }

            btnCancel.Visible     = true;
            btnImport.Enabled     = false;
            pnlImportMain.Visible = true;
            pbImport.IsOnError    = false;
            lvProgress.Items.Clear();

            var worker = new BackgroundWorker
            {
                WorkerReportsProgress      = true,
                WorkerSupportsCancellation = true
            };

            worker.DoWork += (s, evt) =>
            {
                importWorker = (BackgroundWorker)s;

                if (emds.Count == 0)
                {
                    AddTile("Retrieve metadata", "We need entities metadata to process your records");

                    emds = MetadataManager.GetEntitiesList(service);

                    CompleteTile();
                }

                if (iSettings.DeactivateWebPagePlugins)
                {
                    AddTile("Disable plugins", "We need to disable web page plugins to ensure we don't create duplicates");

                    logger.LogInfo("Deactivating Webpage plugins steps");

                    pManager = new PluginManager(service);
                    pManager.DeactivateWebpagePlugins();

                    CompleteTile();

                    logger.LogInfo("Webpage plugins steps deactivated");
                }

                if (iSettings.RemoveJavaScriptFileRestriction && nManager.HasJsRestriction)
                {
                    AddTile("Remove file restriction", "We need to authorize JavaScript file type to create Web file correctly");

                    logger.LogInfo("Removing JavaScript file restriction");

                    nManager.RemoveRestriction();

                    // Wait 2 seconds to be sure the settings is updated
                    Thread.Sleep(2000);

                    CompleteTile();

                    logger.LogInfo("JavaScript file restriction removed");
                }

                AddTile("Process records", "Records are processed in three phases : one phase without lookup being populated. A second phase with lookup being populated. This ensure all relationships between records can be created on the second phase. And a third phase to deactivate records that need it.");

                var rm = new RecordManager(service);
                evt.Cancel = rm.ProcessRecords((EntityCollection)evt.Argument, emds, ConnectionDetail.OrganizationMajorVersion, importWorker, iSettings);

                if (evt.Cancel)
                {
                    CancelTile();
                }
                else
                {
                    CompleteTile();
                }

                if (iSettings.DeactivateWebPagePlugins)
                {
                    AddTile("Enable plugins", "We are enabling web page plugins so that your portal work smoothly");
                    logger.LogInfo("Reactivating Webpage plugins steps");

                    pManager.ActivateWebpagePlugins();

                    logger.LogInfo("Webpage plugins steps activated");
                    CompleteTile();
                }

                if (iSettings.RemoveJavaScriptFileRestriction && nManager.HasJsRestriction)
                {
                    AddTile("Add file restriction", "We are adding back restriction for JavaScript files.");
                    logger.LogInfo("Adding back JavaScript file restriction");

                    importWorker.ReportProgress(0, "Adding back JavaScript file restriction...");
                    nManager.AddRestriction();

                    logger.LogInfo("JavaScript file restriction added back");
                    CompleteTile();
                }
            };
            worker.RunWorkerCompleted += (s, evt) =>
            {
                llOpenLogFile.Visible  = true;
                btnImportClose.Enabled = true;
                btnImport.Enabled      = true;
                btnCancel.Visible      = false;

                if (evt.Cancelled)
                {
                    CancelTile();
                    lblProgress.Text = @"Import was canceled!";
                    return;
                }

                if (evt.Error != null)
                {
                    CancelTile();

                    logger.LogError(evt.Error.ToString());

                    MessageBox.Show(this, $@"An error occured: {evt.Error.Message}", @"Error", MessageBoxButtons.OK,
                                    MessageBoxIcon.Error);
                    return;
                }

                SendMessageToStatusBar?.Invoke(this, new StatusBarMessageEventArgs(string.Empty));
                lblProgress.Text = @"Records imported!";

                if (pbImport.IsOnError)
                {
                    MessageBox.Show(this, @"Import complete with errors

Please review the logs", @"Information", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
                else
                {
                    MessageBox.Show(this, @"Import complete", @"Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            };
            worker.ProgressChanged += (s, evt) =>
            {
                if (evt.UserState is string)
                {
                    lblProgress.Text = evt.UserState.ToString();
                    logger.LogInfo(evt.UserState.ToString());

                    SendMessageToStatusBar?.Invoke(this, new StatusBarMessageEventArgs(evt.UserState.ToString()));
                }
                else
                {
                    if (evt.UserState is ImportProgress progress)
                    {
                        foreach (var ep in progress.Entities)
                        {
                            var item = lvProgress.Items.Cast <ListViewItem>().FirstOrDefault(i => i.Tag.ToString() == ep.LogicalName);
                            if (item == null)
                            {
                                item = new ListViewItem($"{ep.Entity} ({ep.Count})")
                                {
                                    Tag = ep.LogicalName
                                };
                                item.SubItems.Add(ep.SuccessFirstPhase.ToString());
                                item.SubItems.Add(ep.ErrorFirstPhase.ToString());
                                item.SubItems.AddRange(new[] { "", "", "", "" });

                                if (ep.SuccessSecondPhase.HasValue || ep.ErrorSecondPhase.HasValue)
                                {
                                    item.SubItems[3].Text = (ep.SuccessSecondPhase ?? 0).ToString();
                                    item.SubItems[4].Text = (ep.ErrorSecondPhase ?? 0).ToString();
                                }

                                if (ep.SuccessSetStatePhase.HasValue || ep.ErrorSetState.HasValue)
                                {
                                    item.SubItems[5].Text = (ep.SuccessSetStatePhase ?? 0).ToString();
                                    item.SubItems[6].Text = (ep.ErrorSetState ?? 0).ToString();
                                }

                                lvProgress.Items.Add(item);
                            }
                            else
                            {
                                item.SubItems[1].Text = ep.SuccessFirstPhase.ToString();
                                item.SubItems[2].Text = ep.ErrorFirstPhase.ToString();

                                if (ep.SuccessSecondPhase.HasValue || ep.ErrorSecondPhase.HasValue)
                                {
                                    item.SubItems[3].Text = (ep.SuccessSecondPhase ?? 0).ToString();
                                    item.SubItems[4].Text = (ep.ErrorSecondPhase ?? 0).ToString();
                                }

                                if (ep.SuccessSetStatePhase.HasValue || ep.ErrorSetState.HasValue)
                                {
                                    item.SubItems[5].Text = (ep.SuccessSetStatePhase ?? 0).ToString();
                                    item.SubItems[6].Text = (ep.ErrorSetState ?? 0).ToString();
                                }
                            }

                            item.ForeColor = ep.ErrorFirstPhase > 0 || ep.ErrorSecondPhase > 0 || ep.ErrorSetState > 0
                                ? Color.Red
                                : Color.Green;

                            if (ep.ErrorFirstPhase > 0 || ep.ErrorSecondPhase > 0 || ep.ErrorSetState > 0)
                            {
                                pbImport.IsOnError = true;
                            }

                            pbImport.Value = progress.Entities.Sum(ent => ent.Processed) * 100 / progress.Count;
                        }
                    }
                }
            };
            worker.RunWorkerAsync(ec);
        }
        private void Import()
        {
            if (txtImportFilePath.Text.Length == 0)
            {
                return;
            }

            if (!File.Exists(txtImportFilePath.Text))
            {
                MessageBox.Show(this, $"The file {txtImportFilePath.Text} does not exist!", "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            btnCancel.Visible = true;

            lblProgress.Text = "Deserializing file...";
            SendMessageToStatusBar?.Invoke(this, new StatusBarMessageEventArgs("Deserializing file..."));

            EntityCollection ec;

            using (var reader = new StreamReader(txtImportFilePath.Text))
            {
                var serializer = new DataContractSerializer(typeof(EntityCollection), new List <Type> {
                    typeof(Entity)
                });
                ec = (EntityCollection)serializer.ReadObject(reader.BaseStream);
            }

            // References to websites
            var webSitesRefId = ec.Entities.SelectMany(e => e.Attributes)
                                .Where(a => a.Value is EntityReference reference && reference.LogicalName == "adx_website")
                                .Select(a => ((EntityReference)a.Value).Id)
                                .Distinct()
                                .ToList();

            // Websites included in records to process
            var webSitesIds = ec.Entities.Where(e => e.LogicalName == "adx_website")
                              .Select(e => e.Id)
                              .ToList();

            // If some references are not found in websites included in records
            // to process, ask the user to map to the appropriate website
            if (!webSitesRefId.All(id => webSitesIds.Contains(id)))
            {
                var targetWebSites = Service.RetrieveMultiple(new QueryExpression("adx_website")
                {
                    ColumnSet = new ColumnSet("adx_name")
                }).Entities;

                if (!webSitesRefId.All(id => targetWebSites.Select(w => w.Id).Contains(id)))
                {
                    var wsmDialog = new WebSiteMapper(ec, targetWebSites.Select(t => new Website(t)).ToList());
                    if (wsmDialog.ShowDialog() == DialogResult.Cancel)
                    {
                        return;
                    }
                }
            }

            if (ec.Entities.Any(e => e.LogicalName == "adx_webpage"))
            {
                var message =
                    "You are trying to import web pages. It is recommended to deactivate plugins steps related to this entity to ensure successful import. Do you want to deactivate these plugins ? \n\nNote: The plugins will be reactivated at the end of the import process";
                iSettings.DeactivateWebPagePlugins = MessageBox.Show(this, message, @"Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
                                                     DialogResult.Yes;
            }

            if (ec.Entities.Any(e => e.LogicalName == "annotation" && (e.GetAttributeValue <string>("filename")?.ToLower().EndsWith(".js") ?? false)) && nManager.HasJsRestriction)
            {
                var message =
                    "You are trying to import JavaScript note. It is recommended to remove JavaScript file type restriction to ensure successful import. Do you want to remove this restriction ? \n\nNote: The restriction will be added back at the end of the import process";
                iSettings.RemoveJavaScriptFileRestriction = MessageBox.Show(this, message, @"Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
                                                            DialogResult.Yes;
            }

            btnImport.Enabled     = false;
            pnlImportMain.Visible = true;
            pbImport.IsOnError    = false;
            lvProgress.Items.Clear();

            var worker = new BackgroundWorker
            {
                WorkerReportsProgress      = true,
                WorkerSupportsCancellation = true
            };

            worker.DoWork += (s, evt) =>
            {
                importWorker = (BackgroundWorker)s;

                if (emds.Count == 0)
                {
                    importWorker.ReportProgress(0, "Retrieving metadata...");
                    emds = MetadataManager.GetEntitiesList(Service);
                }

                if (iSettings.DeactivateWebPagePlugins)
                {
                    importWorker.ReportProgress(0, "Deactivating Webpage plugins steps...");
                    logger.LogInfo("Deactivating Webpage plugins steps");

                    pManager = new PluginManager(Service);
                    pManager.DeactivateWebpagePlugins();

                    logger.LogInfo("Webpage plugins steps deactivated");
                }

                if (iSettings.RemoveJavaScriptFileRestriction && nManager.HasJsRestriction)
                {
                    logger.LogInfo("Removing JavaScript file restriction");

                    importWorker.ReportProgress(0, "Removing JavaScript file restriction...");
                    nManager.RemoveRestriction();

                    // Wait 2 seconds to be sure the settings is updated
                    Thread.Sleep(2000);

                    logger.LogInfo("JavaScript file restriction removed");
                }

                importWorker.ReportProgress(0, "Processing records...");

                var rm = new RecordManager(Service);
                evt.Cancel = rm.ProcessRecords((EntityCollection)evt.Argument, emds, ConnectionDetail.OrganizationMajorVersion, importWorker);

                if (iSettings.DeactivateWebPagePlugins)
                {
                    importWorker.ReportProgress(0, "Reactivating Webpage plugins steps...");
                    logger.LogInfo("Reactivating Webpage plugins steps");

                    pManager.ActivateWebpagePlugins();

                    logger.LogInfo("Webpage plugins steps activated");
                }

                if (iSettings.RemoveJavaScriptFileRestriction && nManager.HasJsRestriction)
                {
                    logger.LogInfo("Adding back JavaScript file restriction");

                    importWorker.ReportProgress(0, "Adding back JavaScript file restriction...");
                    nManager.AddRestriction();

                    logger.LogInfo("JavaScript file restriction added back");
                }
            };
            worker.RunWorkerCompleted += (s, evt) =>
            {
                SendMessageToStatusBar?.Invoke(this, new StatusBarMessageEventArgs(string.Empty));
                lblProgress.Text      = "Records imported!";
                llOpenLogFile.Visible = true;

                btnImportClose.Enabled = true;
                btnImport.Enabled      = true;
                btnCancel.Visible      = false;

                if (evt.Cancelled)
                {
                    lblProgress.Text = "Import was canceled!";
                    return;
                }

                if (evt.Error != null)
                {
                    MessageBox.Show(this, $"An error occured: {evt.Error.Message}", "Error", MessageBoxButtons.OK,
                                    MessageBoxIcon.Error);
                    return;
                }

                if (pbImport.IsOnError)
                {
                    MessageBox.Show(this, "Import complete with errors\n\nPlease review the logs", "Information", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
                else
                {
                    MessageBox.Show(this, "Import complete", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            };
            worker.ProgressChanged += (s, evt) =>
            {
                if (evt.UserState is string)
                {
                    lblProgress.Text = evt.UserState.ToString();
                    SendMessageToStatusBar?.Invoke(this, new StatusBarMessageEventArgs(evt.UserState.ToString()));
                }
                else
                {
                    var progress = evt.UserState as ImportProgress;
                    if (progress != null)
                    {
                        foreach (var ep in progress.Entities)
                        {
                            var item = lvProgress.Items.Cast <ListViewItem>().FirstOrDefault(i => i.Tag.ToString() == ep.LogicalName);
                            if (item == null)
                            {
                                item = new ListViewItem($"{ep.Entity} ({ep.Count})")
                                {
                                    Tag = ep.LogicalName
                                };
                                item.SubItems.Add(ep.SuccessFirstPhase.ToString());
                                item.SubItems.Add(ep.ErrorFirstPhase.ToString());
                                item.SubItems.AddRange(new[] { "", "", "", "" });

                                if (ep.SuccessSecondPhase.HasValue || ep.ErrorSecondPhase.HasValue)
                                {
                                    item.SubItems[3].Text = (ep.SuccessSecondPhase ?? 0).ToString();
                                    item.SubItems[4].Text = (ep.ErrorSecondPhase ?? 0).ToString();
                                }

                                if (ep.SuccessSetStatePhase.HasValue || ep.ErrorSetState.HasValue)
                                {
                                    item.SubItems[5].Text = (ep.SuccessSetStatePhase ?? 0).ToString();
                                    item.SubItems[6].Text = (ep.ErrorSetState ?? 0).ToString();
                                }

                                lvProgress.Items.Add(item);
                            }
                            else
                            {
                                item.SubItems[1].Text = ep.SuccessFirstPhase.ToString();
                                item.SubItems[2].Text = ep.ErrorFirstPhase.ToString();

                                if (ep.SuccessSecondPhase.HasValue || ep.ErrorSecondPhase.HasValue)
                                {
                                    item.SubItems[3].Text = (ep.SuccessSecondPhase ?? 0).ToString();
                                    item.SubItems[4].Text = (ep.ErrorSecondPhase ?? 0).ToString();
                                }

                                if (ep.SuccessSetStatePhase.HasValue || ep.ErrorSetState.HasValue)
                                {
                                    item.SubItems[5].Text = (ep.SuccessSetStatePhase ?? 0).ToString();
                                    item.SubItems[6].Text = (ep.ErrorSetState ?? 0).ToString();
                                }
                            }

                            if (ep.ErrorFirstPhase > 0 || ep.ErrorSecondPhase > 0 || ep.ErrorSetState > 0)
                            {
                                pbImport.IsOnError = true;
                            }

                            pbImport.Value = progress.Entities.Sum(ent => ent.Processed) * 100 / progress.Count;
                        }
                    }
                }
            };
            worker.RunWorkerAsync(ec);
        }