/// <summary>
        /// Shows the details.
        /// </summary>
        private void ShowDetails()
        {
            UserPreferenceConfiguration userPreferenceConfiguration = this.GetBlockUserPreference(UserPreferenceKey.UserPreferenceConfigurationJSON).FromJsonOrNull <UserPreferenceConfiguration>();

            userPreferenceConfiguration = userPreferenceConfiguration ?? new UserPreferenceConfiguration
            {
                InviteStatuses = cblInviteStatus.SelectedValues.ToArray()
            };

            gpGroups.SetValues(userPreferenceConfiguration.GroupIds ?? new int[0]);
            cbIncludeChildGroups.Checked = userPreferenceConfiguration.IncludeChildGroups;
            cblInviteStatus.SetValues(userPreferenceConfiguration.InviteStatuses);
            UpdateListsForSelectedGroups();

            lbSchedules.SetValues(userPreferenceConfiguration.ScheduleIds ?? new int[0]);
            UpdateLocationListFromSelectedSchedules();

            cblLocations.SetValues(userPreferenceConfiguration.LocationIds ?? new int[0]);
        }
        /// <summary>
        /// Handles the Click event of the btnCreateCommunication control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void btnCreateCommunication_Click(object sender, EventArgs e)
        {
            // Create communication
            var rockContext          = new RockContext();
            var communicationService = new Rock.Model.CommunicationService(rockContext);
            var communication        = new Rock.Model.Communication();

            communication.IsBulkCommunication = false;
            communication.Status = CommunicationStatus.Transient;
            communication.SenderPersonAliasId = this.CurrentPersonAliasId;

            if (this.Request != null && this.Request.Url != null)
            {
                communication.UrlReferrer = this.Request.UrlProxySafe().AbsoluteUri.TrimForMaxLength(communication, "UrlReferrer");
            }

            communicationService.Add(communication);

            // save communication to get Id
            rockContext.SaveChanges();

            int[]      scheduleIds    = lbSchedules.SelectedValuesAsInt.ToArray();
            int[]      locationIds    = cblLocations.SelectedValuesAsInt.ToArray();
            List <int> parentGroupIds = gpGroups.SelectedValuesAsInt().ToList();

            var allGroupIds = new List <int>();

            allGroupIds.AddRange(parentGroupIds);

            if (cbIncludeChildGroups.Checked)
            {
                var groupService = new GroupService(rockContext);
                foreach (var groupId in parentGroupIds)
                {
                    // just the first level of child groups, not all decendants
                    var childGroupIds = groupService.Queryable()
                                        .Where(a => a.ParentGroupId == groupId && a.GroupType.IsSchedulingEnabled && !a.DisableScheduling)
                                        .Select(a => a.Id).ToList();
                    allGroupIds.AddRange(childGroupIds);
                }
            }

            allGroupIds = allGroupIds.Distinct().ToList();

            var attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext);

            var sundayDate = ddlWeek.SelectedValue.AsDateTime() ?? RockDateTime.Now.SundayDate();

            var attendanceOccurrenceQuery = attendanceOccurrenceService
                                            .Queryable()
                                            .Where(a => a.ScheduleId.HasValue && a.LocationId.HasValue && a.GroupId.HasValue)
                                            .WhereDeducedIsActive()
                                            .Where(a => allGroupIds.Contains(a.GroupId.Value))
                                            .Where(a => locationIds.Contains(a.LocationId.Value))
                                            .Where(a => scheduleIds.Contains(a.ScheduleId.Value))
                                            .Where(a => a.SundayDate == sundayDate);

            ScheduledAttendanceItemStatus[] selectedInviteStatus = cblInviteStatus.SelectedValues
                                                                   .Select(a => a.ConvertToEnum <ScheduledAttendanceItemStatus>())
                                                                   .ToArray();

            // limit attendees to ones based on the selected invite status
            var scheduledAttendancesForOccurrenceQuery = attendanceOccurrenceQuery
                                                         .SelectMany(a => a.Attendees)
                                                         .WhereHasScheduledAttendanceItemStatus(selectedInviteStatus);

            var personIds = scheduledAttendancesForOccurrenceQuery.Select(a => a.PersonAlias.PersonId).Distinct().ToList();

            if (!personIds.Any())
            {
                nbCommunicationWarning.Text    = "No people found to send communication to.";
                nbCommunicationWarning.Visible = true;
                return;
            }

            nbCommunicationWarning.Visible = false;

            var personAliasService = new Rock.Model.PersonAliasService(new Rock.Data.RockContext());

            // Get the primary aliases
            List <Rock.Model.PersonAlias> primaryAliasList = new List <PersonAlias>(personIds.Count);

            // get the data in chunks just in case we have a large list of PersonIds (to avoid a SQL Expression limit error)
            var chunkedPersonIds = personIds.Take(1000);
            int skipCount        = 0;

            while (chunkedPersonIds.Any())
            {
                var chunkedPrimaryAliasList = personAliasService.Queryable()
                                              .Where(p => p.PersonId == p.AliasPersonId && chunkedPersonIds.Contains(p.PersonId)).AsNoTracking().ToList();
                primaryAliasList.AddRange(chunkedPrimaryAliasList);
                skipCount       += 1000;
                chunkedPersonIds = personIds.Skip(skipCount).Take(1000);
            }

            // NOTE: Set CreatedDateTime, ModifiedDateTime, etc manually set we are using BulkInsert
            var currentDateTime      = RockDateTime.Now;
            var currentPersonAliasId = this.CurrentPersonAliasId;

            var communicationRecipientList = primaryAliasList.Select(a => new Rock.Model.CommunicationRecipient
            {
                CommunicationId         = communication.Id,
                PersonAliasId           = a.Id,
                CreatedByPersonAliasId  = currentPersonAliasId,
                ModifiedByPersonAliasId = currentPersonAliasId,
                CreatedDateTime         = currentDateTime,
                ModifiedDateTime        = currentDateTime
            }).ToList();

            // BulkInsert to quickly insert the CommunicationRecipient records. Note: This is much faster, but will bypass EF and Rock processing.
            var communicationRecipientRockContext = new RockContext();

            communicationRecipientRockContext.BulkInsert(communicationRecipientList);

            var    pageRef = this.RockPage.Site.CommunicationPageReference;
            string communicationUrl;

            if (pageRef.PageId > 0)
            {
                pageRef.Parameters.AddOrReplace("CommunicationId", communication.Id.ToString());
                communicationUrl = pageRef.BuildUrl();
            }
            else
            {
                communicationUrl = "~/Communication/{0}";
            }

            if (communicationUrl.Contains("{0}"))
            {
                communicationUrl = string.Format(communicationUrl, communication.Id);
            }

            UserPreferenceConfiguration userPreferenceConfiguration = this.GetBlockUserPreference(UserPreferenceKey.UserPreferenceConfigurationJSON).FromJsonOrNull <UserPreferenceConfiguration>() ?? new UserPreferenceConfiguration();

            userPreferenceConfiguration.GroupIds           = gpGroups.SelectedValuesAsInt().ToArray();
            userPreferenceConfiguration.IncludeChildGroups = cbIncludeChildGroups.Checked;
            userPreferenceConfiguration.InviteStatuses     = cblInviteStatus.SelectedValues.ToArray();
            userPreferenceConfiguration.ScheduleIds        = lbSchedules.SelectedValuesAsInt.ToArray();
            userPreferenceConfiguration.LocationIds        = cblLocations.SelectedValuesAsInt.ToArray();
            this.SetBlockUserPreference(UserPreferenceKey.UserPreferenceConfigurationJSON, userPreferenceConfiguration.ToJson());

            Page.Response.Redirect(communicationUrl, false);
            Context.ApplicationInstance.CompleteRequest();
        }