/// <summary>
        ///
        /// </summary>
        /// <param name="gcItem"></param>
        /// <param name="gcTemplate"></param>
        /// <param name="selectedMappingId"></param>
        /// <param name="result"></param>
        /// <param name="selectedLocationId"></param>
        private void TryMapItem(GCItem gcItem, GCTemplate gcTemplate, string selectedMappingId, out MappingResultModel result, string selectedLocationId = null)
        {
            bool isUpdate = gcItem is UpdateGCItem;

            List <Element> gcFields = gcItem.Config.SelectMany(i => i.Elements).ToList();
            var            template = MappingRepository.GetMappingById(selectedMappingId);


            if (template == null)
            {
                string errorMessage = isUpdate ? "Update failed: Template not mapped" : "Import failed: Template not mapped";
                result = new MappingResultModel(gcItem, null, gcTemplate.Name, null, string.Empty, errorMessage, false, selectedLocationId);
                return;
            }

            List <ImportCMSField> fields;

            IEnumerable <IGrouping <string, FieldMapping> > groupedFields = template.FieldMappings.GroupBy(i => i.CmsField.TemplateField.FieldId);

            var files = new List <File>();

            if (gcItem.Config.SelectMany(config => config.Elements).Select(element => element.Type).Contains("files"))
            {
                foreach (var file in ItemsService.GetItemFiles(gcItem.Id.ToString()).Data)
                {
                    files.Add(new File
                    {
                        FileName = file.FileName,
                        Url      = file.Url,

                        UpdatedDate = file.Updated
                    });
                }
            }


            TryMapItemState mapState = TryMapFields(gcFields, groupedFields, files, out fields);

            if (mapState == TryMapItemState.FieldError)
            {
                string errorMessage = isUpdate ? "Update failed: Template fields mismatch" : "Import failed: Template fields mismatch";
                result = new MappingResultModel(gcItem, null, gcTemplate.Name, null, string.Empty, errorMessage, false, selectedLocationId);
                return;
            }

            string cmsId   = string.Empty;
            string message = "Import Successful";

            if (isUpdate)
            {
                cmsId   = (gcItem as UpdateGCItem).CMSId;
                message = "Update Successful";
            }

            result = new MappingResultModel(gcItem, fields, gcTemplate.Name, template.CmsTemplate.TemplateId, cmsId, message, true, selectedLocationId);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="gcTemplateId"></param>
        /// <param name="cmsMappingId"></param>
        /// <returns></returns>
        public MappingModel GetSingleMappingModel(string gcTemplateId, string cmsMappingId)
        {
            if (!string.IsNullOrEmpty(gcTemplateId) && !string.IsNullOrEmpty(cmsMappingId))
            {
                var gcTemplate      = GetGcTemplateEntity(gcTemplateId);
                var gcProject       = GetGcProjectEntity(gcTemplate.Data.ProjectId.ToString());
                var addMappingModel = MappingRepository.GetMappingById(cmsMappingId);
                var model           = MapAddMappingModel(addMappingModel);
                model.GcProject = new GcProjectModel
                {
                    Name = gcProject.Data.Name,
                    Id   = gcProject.Data.Id.ToString()
                };
                model.GcTemplate = new GcTemplateModel
                {
                    Name = gcTemplate.Data.Name,
                    Id   = gcTemplate.Data.Id.ToString()
                };
                model.MappingId = cmsMappingId;
                return(model);
            }

            return(new MappingModel());
        }
        private List <ItemResultModel> Import(string itemId, List <ImportItemModel> items, string projectId, string statusId, string language)
        {
            var model = new List <ItemResultModel>();

            //get all paths
            var fullGcPaths          = GetItemsMap(projectId, items.Select(x => x.Id));
            var pathItemsToBeRemoved = new List <int>();

            Dictionary <string, List <ItemEntity> > shortPaths = new Dictionary <string, List <ItemEntity> >();

            if (fullGcPaths.Count() > 1)
            {
                var firstPath = fullGcPaths.First();
                foreach (var path in firstPath.Value)
                {
                    //if all paths start with same item and this item is not selected
                    if (fullGcPaths.Select(x => x.Value).All(x => x.First().Data.Id == path.Data.Id) && !items.Select(x => x.Id).Contains(path.Data.Id.ToString()))
                    {
                        pathItemsToBeRemoved.Add(path.Data.Id);
                    }
                }
            }

            foreach (var item in fullGcPaths)
            {
                List <ItemEntity> itemsToAdd = new List <ItemEntity>();

                foreach (var gcPathItem in item.Value)
                {
                    if (!pathItemsToBeRemoved.Contains(gcPathItem.Data.Id))
                    {
                        itemsToAdd.Add(gcPathItem);
                    }
                }
                shortPaths.Add(item.Key, itemsToAdd);
            }

            var sorted = shortPaths.OrderBy(x => x.Value.Count).ThenBy(x => x.Value.First().Data.Name);            //sort to start from shortest and alphabetically asc

            foreach (var path in sorted)
            {
                var itemResponseModel = new ItemResultModel
                {
                    IsImportSuccessful = true,
                    ImportMessage      = "Import Successful"
                };

                var gcItem = path.Value.Last();                                            //this is the item we selected to import
                var item   = items.FirstOrDefault(x => x.Id == gcItem.Data.Id.ToString()); //item coming from UI; selected mapping and other info

                if (gcItem != null && gcItem.Data != null && gcItem.Data.TemplateId != null)
                {
                    if (!string.IsNullOrEmpty(GcAccountSettings.GatherContentUrl))
                    {
                        itemResponseModel.GcLink = string.Concat(GcAccountSettings.GatherContentUrl, "/item/", gcItem.Data.Id);
                    }
                    itemResponseModel.GcItem = new GcItemModel
                    {
                        Id    = gcItem.Data.Id.ToString(),
                        Title = gcItem.Data.Name
                    };

                    itemResponseModel.Status = new GcStatusModel
                    {
                        Color = gcItem.Data.Status.Data.Color,
                        Name  = gcItem.Data.Status.Data.Name,
                    };

                    var gcTemplate = TemplatesService.GetSingleTemplate(gcItem.Data.TemplateId.ToString());
                    itemResponseModel.GcTemplate = new GcTemplateModel
                    {
                        Id   = gcTemplate.Data.Id.ToString(),
                        Name = gcTemplate.Data.Name
                    };

                    //element that corresponds to item in CMS that holds mappings
                    TemplateMapping templateMapping = MappingRepository.GetMappingById(item.SelectedMappingId);

                    List <Element> gcFields = gcItem.Data.Config.SelectMany(i => i.Elements).ToList();

                    if (templateMapping != null)                     // template found, now map fields here
                    {
                        var files = new List <File>();
                        if (gcItem.Data.Config.SelectMany(config => config.Elements).Select(element => element.Type).Contains("files"))
                        {
                            foreach (var file in ItemsService.GetItemFiles(gcItem.Data.Id.ToString()).Data)
                            {
                                files.Add(new File
                                {
                                    FileName    = file.FileName,
                                    Url         = file.Url,
                                    FieldId     = file.Field,
                                    UpdatedDate = file.Updated
                                });
                            }
                        }

                        bool fieldError = CheckFieldError(templateMapping, gcFields, files, itemResponseModel);

                        if (!fieldError)
                        {
                            var cmsContentIdField = new FieldMapping
                            {
                                CmsField = new CmsField
                                {
                                    TemplateField = new CmsTemplateField {
                                        FieldName = "GC Content Id"
                                    },
                                    Value = gcItem.Data.Id.ToString()
                                }
                            };
                            templateMapping.FieldMappings.Add(cmsContentIdField);

                            var cmsItem = new CmsItem
                            {
                                Template = templateMapping.CmsTemplate,
                                Title    = gcItem.Data.Name,
                                Fields   = templateMapping.FieldMappings.Select(x => x.CmsField).ToList(),
                                Language = language
                            };

                            var gcPath = string.Join("/", path.Value.Select(x => x.Data.Name));

                            var parentId = itemId;

                            bool alreadyMappedItemInPath = false;
                            //for each mapping which is fact GC Item => Sitecore/Umbraco item - get GC Path and run through its each item
                            for (int i = 0; i < path.Value.Count; i++)
                            {
                                //for each path item check if it exists already in CMS and if yes - skip; otherwise - add not mapped item
                                if (i == path.Value.Count - 1)
                                {
                                    //if we at the last item in the path - import mapped item
                                    if (ItemsRepository.IfMappedItemExists(parentId, cmsItem, templateMapping.MappingId, gcPath))
                                    {
                                        cmsItem.Id = ItemsRepository.AddNewVersion(parentId, cmsItem, templateMapping.MappingId, gcPath);
                                    }
                                    else
                                    {
                                        cmsItem.Id = ItemsRepository.CreateMappedItem(parentId, cmsItem, templateMapping.MappingId, gcPath);
                                    }
                                    parentId = cmsItem.Id;

                                    var fieldMappings = templateMapping.FieldMappings;

                                    // one CMS text field can be mapped to several GC fields
                                    // in this case we concatenate their texts and put into one CMS field
                                    foreach (IGrouping <string, FieldMapping> fields in fieldMappings.GroupBy(f => f.CmsField.TemplateField.FieldName))
                                    {
                                        var fieldMappingsAdditionals = fields
                                                                       .Where(f => f.CmsFieldAdditionalMapping != null &&
                                                                              f.CmsFieldAdditionalMapping.Any()).ToList()
                                                                       .SelectMany(f => f.CmsFieldAdditionalMapping).ToList();

                                        FieldMapping field = fields.First();
                                        if (field.GcField != null)
                                        {
                                            foreach (var fieldMappingsAdditional in fieldMappingsAdditionals)
                                            {
                                                fieldMappingsAdditional.Value   = field.CmsField.Value;
                                                fieldMappingsAdditional.Files   = field.CmsField.Files;
                                                fieldMappingsAdditional.Options = field.CmsField.Options;
                                            }

                                            switch (field.GcField.Type)
                                            {
                                            case "choice_radio":
                                            case "choice_checkbox":
                                            {
                                                ItemsRepository.MapChoice(cmsItem, field.CmsField);
                                                foreach (var fieldMappingsAdditional in fieldMappingsAdditionals)
                                                {
                                                    ItemsRepository.MapChoice(cmsItem, fieldMappingsAdditional);
                                                }
                                            }
                                            break;

                                            case "files":
                                            {
                                                ItemsRepository.ResolveAttachmentMapping(cmsItem, field.CmsField);
                                                foreach (var fieldMappingsAdditional in fieldMappingsAdditionals)
                                                {
                                                    ItemsRepository.ResolveAttachmentMapping(cmsItem, fieldMappingsAdditional);
                                                }
                                            }
                                            break;

                                            default:
                                            {
                                                if (field.CmsField.TemplateField.FieldType == "Datetime" || field.CmsField.TemplateField.FieldType == "Date")
                                                {
                                                    ItemsRepository.MapDateTime(cmsItem, field.CmsField);
                                                    foreach (var fieldMappingsAdditional in fieldMappingsAdditionals)
                                                    {
                                                        ItemsRepository.MapDateTime(cmsItem, fieldMappingsAdditional);
                                                    }
                                                }
                                                else
                                                {
                                                    if (fields.Count() > 1)
                                                    {
                                                        var newValue = string.Join("\r\n", fields.Select(f => f.CmsField.Value.ToString()));
                                                        field.CmsField.Value = newValue;
                                                        fieldMappingsAdditionals.ForEach(f => f.Value = newValue);
                                                    }

                                                    ItemsRepository.MapText(cmsItem, field.CmsField);
                                                    foreach (var fieldMappingsAdditional in fieldMappingsAdditionals)
                                                    {
                                                        ItemsRepository.MapText(cmsItem, fieldMappingsAdditional);
                                                    }
                                                }
                                            }
                                            break;
                                            }
                                        }
                                    }

                                    //Publish Parent Image Folder with SubItems?

                                    string parentMediaFolder = SimpleMediaRepository.publishParentMediaFolder;
                                    ItemsRepository.PublishItems(parentMediaFolder, isMediaFolder: true);
                                    ItemsRepository.PublishItems(cmsItem.Id, isContentItem: true);


                                    //set CMS link after we got out CMS Id
                                    var cmsLink = ItemsRepository.GetCmsItemLink(HttpContext.Current.Request.Url.Scheme, HttpContext.Current.Request.Url.Host, cmsItem.Id);
                                    itemResponseModel.CmsLink = cmsLink;
                                    itemResponseModel.CmsId   = cmsItem.Id;

                                    if (!string.IsNullOrEmpty(statusId))
                                    {
                                        var status = PostNewItemStatus(gcItem.Data.Id.ToString(), statusId, projectId);
                                        itemResponseModel.Status.Color = status.Color;
                                        itemResponseModel.Status.Name  = status.Name;
                                    }
                                }
                                else
                                {
                                    var currentCmsItem = new CmsItem
                                    {
                                        Title    = path.Value[i].Data.Name,
                                        Language = language
                                    };
                                    //if we are not at the selected item, somewhere in the middle
                                    //1. если замапленный айтем существует (такое же название и такой же gc path?), то тогда выставляем alreadyMappedItemInPath = тру
                                    //и пропускаем всякое создание, сеттим только парент id
                                    //2. иначе если есть незамапленный айтем:
                                    // - alreadyMappedItemInPath == true = - скипуем создание, выставляем его как парент айди
                                    // - alreadyMappedItemInPath == false, - скипуем всё, парент айди не меняем
                                    //3. айтема никакого нет
                                    // - alreadyMappedItemInPath == true = - создаём незамапленный айтем, выставляем его как парент айди
                                    // - alreadyMappedItemInPath == false, - скипуем всё, парент айди не меняем
                                    if (ItemsRepository.IfMappedItemExists(parentId, currentCmsItem))
                                    {
                                        //cmsItem.Id = ItemsRepository.CreateNotMappedItem(parentId, notMappedCmsItem);
                                        //parentId = cmsItem.Id;
                                        alreadyMappedItemInPath = true;
                                        parentId = ItemsRepository.GetItemId(parentId, currentCmsItem);
                                    }
                                    else if (ItemsRepository.IfNotMappedItemExists(parentId, currentCmsItem))
                                    {
                                        if (alreadyMappedItemInPath)
                                        {
                                            parentId = ItemsRepository.GetItemId(parentId, currentCmsItem);
                                        }
                                    }
                                    else
                                    {
                                        if (alreadyMappedItemInPath)
                                        {
                                            parentId = ItemsRepository.CreateNotMappedItem(parentId, currentCmsItem);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        //no template mapping, set error message
                        itemResponseModel.ImportMessage      = "Import failed: Template not mapped";
                        itemResponseModel.IsImportSuccessful = false;
                    }
                }
                model.Add(itemResponseModel);
            }

            return(model);
        }