public async Task<ActionResult> Create(EditViewModel viewModel)
 {
     return await EditPostCore(viewModel);
 }
        public async Task<ActionResult> Edit(int id)
        {
            var userId = GetUserId();
            var context = this.DbContext;

            var filter = await context.Filters
                .Include(o => o.FilterProperties)
                .Where(o => o.FilterId == id && o.UserId == userId)
                .FirstOrDefaultAsync();
            if (filter == null)
                return HttpNotFound("Could not find filter.");

            var viewModel = new EditViewModel();
            InitializeEditViewModel(viewModel, filter);
            return View(viewModel);
        }
        private bool ApplyEdits(EditViewModel viewModel, GMailLabelCleanup.Data.Models.Filters.Filter filter)
        {
            System.Diagnostics.Debug.Assert(viewModel != null);
            System.Diagnostics.Debug.Assert(filter != null);

            bool hasChanges = false;

            //Apply high level properties
            if (!string.Equals(filter.Description, viewModel.Description))
            {
                filter.Description = viewModel.Description;
                hasChanges = true;
            }

            foreach (var item in viewModel.ActionProperties.Concat(viewModel.CriteriaProperties).Where(o => o.IsCheckType))
            {
                item.Value = item.IsChecked ? "true" : "false";
            }

            /*
             * New properties:
             * ViewModel properties that are included and whose
             * name does not appear in the Filter.FilterProperties.
             * 
             * Updated properies:
             * ViewModel properties whose
             * name appears in the Filter.FilterProperties.
             */

            var existingPropertyNames = filter.FilterProperties
                .Select(o => o.Name)
                .ToHashSet();

            var allProperties = viewModel.CriteriaProperties
                .Concat(viewModel.ActionProperties)
                .ToArray();

            var newProperties = allProperties
                .Where(o => !existingPropertyNames.Contains(o.Name));
            var updatedProperties = allProperties
                .Where(o => existingPropertyNames.Contains(o.Name));

            var dateCreated = DateTime.UtcNow;

            foreach (var item in updatedProperties)
            {
                var matches = filter.FilterProperties
                   .Where(o => string.Equals(o.Name, item.Name) && (!string.Equals(o.Value, item.Value) || o.IsIncluded != item.IsIncluded))
                   .ToArray();

                foreach (var match in matches)
                {
                    match.IsIncluded = item.IsIncluded;
                    match.Value = item.Value;
                    hasChanges = true;
                }
            }
            foreach (var item in newProperties)
            {
                filter.FilterProperties.Add(new FilterProperty
                {
                    IsIncluded = item.IsIncluded,
                    Name = item.Name,
                    Value = item.Value,
                    DateCreatedUtc = dateCreated
                });
                hasChanges = true;
            }
            return hasChanges;
        }
 public ActionResult Create()
 {
     var viewModel = new EditViewModel();
     InitializeEditViewModel(viewModel, null);
     return View(viewModel);
 }
        private void ValidateProperties(EditViewModel viewModel)
        {
            System.Diagnostics.Debug.Assert(viewModel != null);

            if (!viewModel.CriteriaProperties.Any(o => o.IsIncluded))
            {
                ModelState.AddModelError("CriteriaProperties", "At least one criteria must be applied.");
            }
            if (!viewModel.ActionProperties.Any(o => o.IsIncluded))
            {
                ModelState.AddModelError("ActionProperties", "At least one action must be applied.");
            }
        }
        private async Task<ActionResult> EditPostCore(EditViewModel viewModel)
        {
            System.Diagnostics.Debug.Assert(viewModel != null);

            ValidateProperties(viewModel);
            if (!ModelState.IsValid)
            {
                InitializeEditSelectLists(viewModel);
                return View(viewModel);
            }

            var userId = GetUserId();
            var context = this.DbContext;

            var isNew = viewModel.Id == 0;

            GMailLabelCleanup.Data.Models.Filters.Filter filter;
            if (!isNew)
            {
                filter = await context.Filters
                    .Include(o => o.FilterProperties)
                    .Where(o => o.FilterId == viewModel.Id && o.UserId == userId)
                    .FirstOrDefaultAsync();

                if (filter == null)
                    return HttpNotFound("Could not find filter.");
            }
            else
            {
                filter = new GMailLabelCleanup.Data.Models.Filters.Filter
                {
                    UserId = userId,
                    DateCreatedUtc = DateTime.UtcNow,
                    Description = viewModel.Description,
                    FilterProperties = new List<FilterProperty>()
                };
            }

            if (isNew)
            {
                context.Filters.Add(filter);
            }

            if (ApplyEdits(viewModel, filter) || isNew)
            {
                await context.SaveChangesAsync();

                if (isNew)
                {
                    await Task.Run(() => new TelemetryClient().TrackEvent("CreateFilter"));
                }
                else
                {
                    await Task.Run(() => new TelemetryClient().TrackEvent("EditFilter"));
                }
            }

            return RedirectToAction("Index");
        }
        private void InitializeEditProperties(EditViewModel viewModel, IList<FilterProperty> properties)
        {
            System.Diagnostics.Debug.Assert(viewModel != null);
            System.Diagnostics.Debug.Assert(properties != null);

            var component = new MessageFilterComponent();

            viewModel.CriteriaProperties = new List<EditPropertyViewModel>();
            viewModel.ActionProperties = new List<EditPropertyViewModel>();

            foreach (var pair in MessageFilterComponent.CriteriaPropertyNames)
            {
                var existingProperty = properties
                    .FirstOrDefault(o => o.Name == pair.Value);

                viewModel.CriteriaProperties.Add(CreateEditPropertyViewModel(component, existingProperty, pair.Value));
            }

            foreach (var pair in MessageFilterComponent.ActionPropertyNames)
            {
                var existingProperty = properties
                    .FirstOrDefault(o => o.Name == pair.Value);

                viewModel.ActionProperties.Add(CreateEditPropertyViewModel(component, existingProperty, pair.Value));
            }
        }
        private void InitializeEditSelectLists(EditViewModel viewModel)
        {
            System.Diagnostics.Debug.Assert(viewModel != null);

            var smartLabels = new SelectList(new[]
            {
                new { ID = (int)SmartLabelType.Personal, Name = "Personal" },
                new { ID = (int)SmartLabelType.Social, Name = "Social" },
                new { ID = (int)SmartLabelType.Promotions, Name = "Promotions" },
                new { ID = (int)SmartLabelType.Notification, Name = "Updates" },
                new { ID = (int)SmartLabelType.Group, Name = "Forums" }
            }, "ID", "Name");
            var sizeUnits = new SelectList(new[]
            {
                new { ID = (int)SizeUnitType.MB, Name = "MB" },
                new { ID = (int)SizeUnitType.KB, Name = "KB" },
                new { ID = (int)SizeUnitType.Byte, Name = "Bytes" }
            }, "ID", "Name");
            var sizeOperators = new SelectList(new[]
            {
                new { ID = (int)SizeOperatorType.GreaterThan, Name = "Greater than" },
                new { ID = (int)SizeOperatorType.LessThan, Name = "Less than" }
            }, "ID", "Name");

            viewModel.SmartLabels = smartLabels;
            viewModel.SizeOperators = sizeOperators;
            viewModel.SizeUnits = sizeUnits;
        }
        private void InitializeEditViewModel(EditViewModel viewModel, GMailLabelCleanup.Data.Models.Filters.Filter filter)
        {
            System.Diagnostics.Debug.Assert(viewModel != null);

            viewModel.Id = filter != null ? filter.FilterId : 0;
            viewModel.Description = filter != null ? filter.Description : string.Empty;

            InitializeEditSelectLists(viewModel);
            InitializeEditProperties(viewModel, filter != null ? filter.FilterProperties : new FilterProperty[] { });
        }