public override void DeleteItems(List <DataCompareItem> items, IDataSynchronizationStatus status)
        {
            if (items != null && items.Count > 0)
            {
                int currentItem = 0;

                foreach (var item in items)
                {
                    if (!status.ContinueProcessing)
                    {
                        break;
                    }

                    var itemInvariant = new DataCompareItemInvariant(item);

                    //Example: Get the item ID from the Target Identifier Store
                    var item_id = itemInvariant.GetTargetIdentifier <int>();

                    try
                    {
                        //Call the Automation BeforeDeleteItem (Optional only required if your supporting Automation Item Events)
                        Automation?.BeforeDeleteItem(this, itemInvariant, item_id);

                        if (itemInvariant.Sync)
                        {
                            #region Delete Item

                            var result = WebRequestHelper.DeleteRequestAsJson(null, DatasourceInfo.GetPipedriveItemEndpointUrl(item_id));

                            #endregion

                            //Call the Automation AfterDeleteItem
                            Automation?.AfterDeleteItem(this, itemInvariant, item_id);
                        }

                        ClearSyncStatus(item); //Clear the Sync Flag on Processed Rows
                    }
                    catch (WebException e)
                    {
                        Automation?.ErrorItem(this, itemInvariant, item_id, e);
                        HandleError(status, e);
                    }
                    catch (SystemException e)
                    {
                        Automation?.ErrorItem(this, itemInvariant, item_id, e);
                        HandleError(status, e);
                    }
                    finally
                    {
                        status.Progress(items.Count, ++currentItem); //Update the Sync Progress
                    }
                }
            }
        }
        public override void DeleteItems(List <DataCompareItem> items, IDataSynchronizationStatus status)
        {
            if (items != null && items.Count > 0)
            {
                int currentItem = 0;

                foreach (var item in items)
                {
                    if (!status.ContinueProcessing)
                    {
                        break;
                    }

                    try
                    {
                        var itemInvariant = new DataCompareItemInvariant(item);
                        var filename      = itemInvariant.GetTargetIdentifier <string>();

                        Automation?.BeforeDeleteItem(this, itemInvariant, filename);

                        if (itemInvariant.Sync)
                        {
                            try
                            {
                                Session.RemoveFile(filename);
                                Automation?.AfterDeleteItem(this, itemInvariant, filename);
                            }
                            catch (Exception e)
                            {
                                Automation?.ErrorItem(this, itemInvariant, filename, e);
                                throw;
                            }
                        }

                        ClearSyncStatus(item); //Clear the Sync Flag on Processed Rows
                    }
                    catch (SystemException e)
                    {
                        HandleError(status, e);
                    }
                    finally
                    {
                        status.Progress(items.Count, ++currentItem); //Update the Sync Progress
                    }
                }
            }
        }
        public override void UpdateItems(List <DataCompareItem> items, IDataSynchronizationStatus status)
        {
            if (items != null && items.Count > 0)
            {
                int currentItem = 0;

                foreach (var item in items)
                {
                    if (!status.ContinueProcessing)
                    {
                        break;
                    }

                    try
                    {
                        var itemInvariant = new DataCompareItemInvariant(item);
                        var filename      = itemInvariant.GetTargetIdentifier <string>();

                        Automation?.BeforeUpdateItem(this, itemInvariant, filename);

                        if (itemInvariant.Sync)
                        {
                            #region Update Item

                            //Get the Target Item Data
                            Dictionary <string, object> targetItem = UpdateItemToDictionary(Mapping, itemInvariant);

                            string tmpFile = System.IO.Path.Combine(Utility.GetTempPath(), $"{Guid.NewGuid()}.tmp");

                            try
                            {
                                System.IO.File.WriteAllBytes(tmpFile, SourceReader.GetBlobData(itemInvariant.ToDataCompareItem(), 0));
                                if (targetItem.TryGetValue("DateModified", out object value))
                                {
                                    System.IO.File.SetLastWriteTimeUtc(tmpFile, DataSchemaTypeConverter.ConvertTo <DateTime>(value).ToUniversalTime());
                                }

                                Session.PutFiles(tmpFile, filename, false, new TransferOptions {
                                    OverwriteMode = OverwriteMode.Overwrite, PreserveTimestamp = true, TransferMode = TransferMode.Binary
                                }).Check();
                            }
                            catch (Exception e)
                            {
                                Automation?.ErrorItem(this, itemInvariant, filename, e);
                                throw;
                            }
                            finally
                            {
                                if (System.IO.File.Exists(tmpFile))
                                {
                                    System.IO.File.Delete(tmpFile);
                                }
                            }

                            Automation?.AfterUpdateItem(this, itemInvariant, filename);
                            #endregion
                        }

                        ClearSyncStatus(item); //Clear the Sync Flag on Processed Rows
                    }
                    catch (SystemException e)
                    {
                        HandleError(status, e);
                    }
                    finally
                    {
                        status.Progress(items.Count, ++currentItem); //Update the Sync Progress
                    }
                }
            }
        }
        public override void AddItems(List <DataCompareItem> items, IDataSynchronizationStatus status)
        {
            if (items != null && items.Count > 0)
            {
                int currentItem = 0;

                foreach (var item in items)
                {
                    if (!status.ContinueProcessing)
                    {
                        break;
                    }

                    var itemInvariant = new DataCompareItemInvariant(item);

                    try
                    {
                        //Call the Automation BeforeAddItem
                        Automation?.BeforeAddItem(this, itemInvariant, null);

                        if (itemInvariant.Sync)
                        {
                            #region Add Item

                            //Get the Target Item Data
                            var targetItem       = AddItemToDictionary(Mapping, itemInvariant);
                            var targetItemToSend = new Dictionary <string, object>();

                            foreach (var k in targetItem.Keys)
                            {
                                var val = targetItem[k];

                                if (val == null)
                                {
                                    continue;
                                }

                                var pdsi = DataSchema[k];
                                targetItemToSend[pdsi.Key] = pdsi.Parser.ConvertValue(val);
                            }

                            if (targetItemToSend.Any())
                            {
                                var json    = JsonConvert.SerializeObject(targetItemToSend, Formatting.None);
                                var result  = WebRequestHelper.PostRequestAsJson(json, DatasourceInfo.PipedriveEndpointUrl);
                                var item_id = result["data"]["id"].ToObject <int>();

                                //Call the Automation AfterAddItem
                                Automation?.AfterAddItem(this, itemInvariant, item_id);
                            }

                            #endregion
                        }

                        ClearSyncStatus(item); //Clear the Sync Flag on Processed Rows
                    }
                    catch (WebException e)
                    {
                        Automation?.ErrorItem(this, itemInvariant, null, e);
                        HandleError(status, e);
                    }
                    catch (SystemException e)
                    {
                        Automation?.ErrorItem(this, itemInvariant, null, e);
                        HandleError(status, e);
                    }
                    finally
                    {
                        status.Progress(items.Count, ++currentItem); //Update the Sync Progress
                    }
                }
            }
        }
        public override void AddItems(List <DataCompareItem> items, IDataSynchronizationStatus status)
        {
            if (items != null && items.Count > 0)
            {
                int currentItem = 0;

                foreach (var item in items)
                {
                    if (!status.ContinueProcessing)
                    {
                        break;
                    }

                    var itemInvariant = new DataCompareItemInvariant(item);

                    try
                    {
                        //Call the Automation BeforeAddItem (Optional only required if your supporting Automation Item Events)
                        Automation?.BeforeAddItem(this, itemInvariant, null);

                        if (itemInvariant.Sync)
                        {
                            #region Add Item

                            //Get the Target Item Data
                            var targetItem       = AddItemToDictionary(Mapping, itemInvariant);
                            var targetItemToSend = new Dictionary <string, object>();

                            foreach (var k in targetItem.Keys)
                            {
                                if (!MailChimpDataSchema.ContainsKey(k))
                                {
                                    continue;
                                }

                                var mc = MailChimpDataSchema[k];

                                if (mc.ReadOnly)
                                {
                                    continue;
                                }

                                if (mc.IsSubValue)
                                {
                                    if (mc.IsArray)
                                    {
                                        if (mc.ObjectName == "tags")
                                        {
                                            // If Tags - create an array of Tags to add.
                                            targetItemToSend[mc.ObjectName] = DataSchemaTypeConverter.ConvertTo <string[]>(targetItem[k]);
                                        }
                                    }
                                    else
                                    {
                                        if (!targetItemToSend.ContainsKey(mc.ObjectName))
                                        {
                                            targetItemToSend[mc.ObjectName] = new Dictionary <string, object>();
                                        }

                                        var subValue = targetItemToSend[mc.ObjectName] as Dictionary <string, object>;

                                        subValue[mc.FieldName] = targetItem[k];
                                    }
                                }
                                else
                                {
                                    targetItemToSend[mc.FieldName] = targetItem[k];
                                }
                            }

                            var json    = JsonConvert.SerializeObject(targetItemToSend, Formatting.None);
                            var result  = WebRequestHelper.PostRequestAsJson(json, $"{ListServiceUrl}/{DataSourceReader.ListId}/members");
                            var item_id = result["id"].ToObject <string>();

                            //Call the Automation AfterAddItem (pass the created item identifier if possible)
                            Automation?.AfterAddItem(this, itemInvariant, item_id);
                        }

                        #endregion

                        ClearSyncStatus(item); //Clear the Sync Flag on Processed Rows
                    }
                    catch (WebException e)
                    {
                        Automation?.ErrorItem(this, itemInvariant, null, e);
                        HandleError(status, e);
                    }
                    catch (SystemException e)
                    {
                        Automation?.ErrorItem(this, itemInvariant, null, e);
                        HandleError(status, e);
                    }
                    finally
                    {
                        status.Progress(items.Count, ++currentItem); //Update the Sync Progress
                    }
                }
            }
        }
        public override void UpdateItems(List <DataCompareItem> items, IDataSynchronizationStatus status)
        {
            if (items != null && items.Count > 0)
            {
                int currentItem = 0;

                foreach (var item in items)
                {
                    if (!status.ContinueProcessing)
                    {
                        break;
                    }

                    var itemInvariant = new DataCompareItemInvariant(item);

                    // Get the item ID from the Target Identifier Store
                    var item_id = itemInvariant.GetTargetIdentifier <string>();

                    try
                    {
                        //Call the Automation BeforeUpdateItem (Optional only required if your supporting Automation Item Events)
                        Automation?.BeforeUpdateItem(this, itemInvariant, item_id);

                        if (itemInvariant.Sync)
                        {
                            #region Update Item

                            //Get the Target Item Data
                            var targetItem       = UpdateItemToDictionary(Mapping, itemInvariant);
                            var targetItemToSend = new Dictionary <string, object>();

                            foreach (var k in targetItem.Keys)
                            {
                                if (!MailChimpDataSchema.ContainsKey(k))
                                {
                                    continue;
                                }

                                var mc = MailChimpDataSchema[k];

                                if (mc.ReadOnly)
                                {
                                    continue;
                                }

                                if (mc.IsSubValue)
                                {
                                    if (mc.IsArray)
                                    {
                                        if (mc.ObjectName == "tags")
                                        {
                                            // If Tags - get the original list of tags and work out which ones to add/remove

                                            var source_item = itemInvariant.Row.First(p => Mapping.MapColumnToDestination(p) == k);

                                            var existing = GetHashSet <string>(source_item.BeforeColumnValue);
                                            var toadd    = GetHashSet <string>(source_item.AfterColumnValue);

                                            var arrayOfDictionary = new List <Dictionary <string, object> >();

                                            // Tags to Add
                                            foreach (var v in toadd.Except(existing))
                                            {
                                                arrayOfDictionary.Add(new Dictionary <string, object>()
                                                {
                                                    { "name", v }, { "status", "active" }
                                                });
                                            }

                                            // Tags to Remove
                                            foreach (var v in existing.Except(toadd))
                                            {
                                                arrayOfDictionary.Add(new Dictionary <string, object>()
                                                {
                                                    { "name", v }, { "status", "inactive" }
                                                });
                                            }

                                            var tags_json   = JsonConvert.SerializeObject(new { tags = arrayOfDictionary }, Formatting.None);
                                            var tags_result = WebRequestHelper.PostRequestAsJson(tags_json, $"{ListServiceUrl}/{DataSourceReader.ListId}/members/{item_id}/tags");
                                        }
                                    }
                                    else
                                    {
                                        if (!targetItemToSend.ContainsKey(mc.ObjectName))
                                        {
                                            targetItemToSend[mc.ObjectName] = new Dictionary <string, object>();
                                        }

                                        var subValue = targetItemToSend[mc.ObjectName] as Dictionary <string, object>;

                                        subValue[mc.FieldName] = targetItem[k];
                                    }
                                }
                                else
                                {
                                    targetItemToSend[mc.FieldName] = targetItem[k];
                                }
                            }

                            if (targetItemToSend.Any())
                            {
                                var json   = JsonConvert.SerializeObject(targetItemToSend, Formatting.None);
                                var result = WebRequestHelper.PutRequestAsJson(json, $"{ListServiceUrl}/{DataSourceReader.ListId}/members/{item_id}");
                            }


                            //Call the Automation AfterUpdateItem
                            Automation?.AfterUpdateItem(this, itemInvariant, item_id);


                            #endregion
                        }

                        ClearSyncStatus(item); //Clear the Sync Flag on Processed Rows
                    }
                    catch (WebException e)
                    {
                        Automation?.ErrorItem(this, itemInvariant, item_id, e);
                        HandleError(status, e);
                    }
                    catch (SystemException e)
                    {
                        Automation?.ErrorItem(this, itemInvariant, item_id, e);
                        HandleError(status, e);
                    }
                    finally
                    {
                        status.Progress(items.Count, ++currentItem); //Update the Sync Progress
                    }
                }
            }
        }