/// <summary>
        ///
        /// </summary>
        /// <param name="pluginExecutionFacade"></param>
        /// <param name="newTimeEntryDto"></param>
        /// <returns></returns>
        private IEnumerable <DateTime> GetExistingTimeEntryDates(PluginExecutionFacade pluginExecutionFacade, TimeEntryDto newTimeEntryDto)
        {
            var queryExpression = TimeEntryQueryExpressionBuilder.Build(new GetEntryTimeRangeRequest(
                                                                            start: newTimeEntryDto.Start,
                                                                            end: newTimeEntryDto.End,
                                                                            resourceId: newTimeEntryDto.BookableResource.Id));
            var service          = pluginExecutionFacade.OrganizationService;
            var entityCollection = service.RetrieveMultiple(queryExpression);

            return(entityCollection.Entities.Select(e => e.GetAttributeValue <DateTime>(TimeEntry.Properties.Start).ToUniversalTime().Date));
        }
        public void Execute(IServiceProvider serviceProvider)
        {
            // https://docs.microsoft.com/ru-ru/powerapps/developer/data-platform/best-practices/business-logic/develop-iplugin-implementations-stateless#problematic-patterns
            // to avoid problematic pattern should create pluginExecutionFacade and pass it everywhere (instead of using a variable of class)
            var pluginExecutionFacade = new PluginExecutionFacade(serviceProvider);

            try
            {
                var context = pluginExecutionFacade.Context;
                // if another plugin creates TimeEntry then this check should be removed
                if (context.Depth > 1)
                {
                    return;
                }
                var targetEntity       = context.InputParameters.GetTargetEntity();
                var targetTimeEntryDto = TimeEntryDtoConverter.ConvertToDto(targetEntity);

                if (targetTimeEntryDto.End.Date <= targetTimeEntryDto.Start.Date)
                {
                    return;
                }
                // the main logic is located here for clarity
                var existingTimeEntrieDates = GetExistingTimeEntryDates(pluginExecutionFacade, targetTimeEntryDto);
                var date             = targetTimeEntryDto.Start.Date;
                var maxDate          = targetTimeEntryDto.End.Date;
                var datesToBeCreated = new List <DateTime>();
                while (date <= maxDate)
                {
                    if (!existingTimeEntrieDates.Contains(date))
                    {
                        datesToBeCreated.Add(date);
                    }
                    date = date.AddDays(1);
                }

                if (!datesToBeCreated.Any())
                {
                    throw new InvalidPluginExecutionException("Duplicates creation is canceled");
                }

                // target TimeEntry should be changed
                var firstDateToBeCreated = datesToBeCreated[0];
                if (targetTimeEntryDto.Start.Date == firstDateToBeCreated)
                {
                    var duration = targetTimeEntryDto.Start.EndOfTheDay() - targetTimeEntryDto.Start;
                    targetEntity.SetDuration(duration);
                    targetEntity.SetEnd(targetTimeEntryDto.Start + duration);
                }
                else
                {
                    var duration = TimeSpan.FromDays(1) - TimeSpan.FromMinutes(1);
                    targetEntity.SetStart(firstDateToBeCreated);
                    targetEntity.SetDuration(duration);
                    targetEntity.SetEnd(firstDateToBeCreated + duration);
                }
                // the first TimeEntry will be created later as the "target" TimeEntry
                datesToBeCreated.RemoveAt(0);

                foreach (var dateItem in datesToBeCreated)
                {
                    var duration  = (TimeSpan.FromDays(1) - TimeSpan.FromMinutes(1));
                    var newEntity = targetEntity.Clone();
                    newEntity.SetStart(dateItem);
                    newEntity.SetDuration(duration);
                    newEntity.SetEnd(dateItem + duration);
                    pluginExecutionFacade.OrganizationService.Create(newEntity);
                }
            }
            catch (Exception ex)
            {
                pluginExecutionFacade.TracingService.Trace("{0}: {1}", nameof(TimeEntryUniqueDatePlugin), ex.ToString());
                // just to debug
                throw new InvalidPluginExecutionException($"An error occurred in {nameof(TimeEntryUniqueDatePlugin)}.", ex);
            }
        }