/// <summary>
        /// Returns an individual's unique assignment schedule list.
        /// </summary>
        /// <param name="groupGuid"></param>
        /// <returns>A list of <see cref="ListItemViewModel"/> to be passed into mobile.</returns>
        private List <ListItemViewModel> GetSpecificAssignmentScheduleList(Guid groupGuid)
        {
            using (var rockContext = new RockContext())
            {
                // Get the group.
                var group = new GroupService(rockContext).Get(groupGuid);

                var groupLocationService = new GroupLocationService(rockContext);
                var scheduleList         = groupLocationService
                                           .Queryable()
                                           .AsNoTracking()
                                           .Where(g => g.Group.Guid == groupGuid)
                                           .SelectMany(g => g.Schedules)
                                           .Distinct()
                                           .ToList();

                List <Schedule> sortedScheduleList = scheduleList.OrderByOrderAndNextScheduledDateTime();

                GroupMemberAssignmentService groupMemberAssignmentService = new GroupMemberAssignmentService(rockContext);
                int?groupMemberId = null;

                var groupMember = GetGroupMemberRecord(rockContext, group.Id, CurrentPersonId);
                if (groupMember != null)
                {
                    groupMemberId = groupMember.Id;
                }

                // Shouldn't happen, but we'll be cautious.
                if (!groupMemberId.HasValue)
                {
                    return(null);
                }

                var configuredScheduleIds = groupMemberAssignmentService.Queryable()
                                            .Where(a => a.GroupMemberId == groupMemberId.Value && a.ScheduleId.HasValue)
                                            .Select(s => s.ScheduleId.Value)
                                            .Distinct()
                                            .ToList();

                // Limit to schedules that haven't had a schedule preference set yet.
                sortedScheduleList = sortedScheduleList
                                     .Where(a => !configuredScheduleIds.Contains(a.Id))
                                     .ToList();

                var scheduleListItems = new List <ListItemViewModel>();

                foreach (var value in sortedScheduleList)
                {
                    var scheduleListItem = new ListItemViewModel
                    {
                        Value = value.Guid.ToStringSafe(),
                        Text  = value.Name
                    };

                    scheduleListItems.Add(scheduleListItem);
                }

                return(scheduleListItems);
            }
        }
        public BlockActionResult SaveSpecificAssignmentSchedule(Guid?groupGuid, Guid scheduleGuid, Guid?locationGuid)
        {
            using (var rockContext = new RockContext())
            {
                // Get the group.
                var group = new GroupService(rockContext).GetNoTracking(groupGuid.Value);

                // Get the specific group member assignment.
                GroupMemberAssignmentService groupMemberAssignmentService = new GroupMemberAssignmentService(rockContext);
                var groupMember = GetGroupMemberRecord(rockContext, group.Id, this.CurrentPersonId);

                var schedule = new ScheduleService(rockContext).GetNoTracking(scheduleGuid);

                int?locationId = null;
                if (locationGuid != null)
                {
                    var location = new LocationService(rockContext).GetNoTracking(locationGuid.Value);

                    if (location != null)
                    {
                        locationId = location.Id;
                    }
                }

                var groupMemberAssignment = groupMemberAssignmentService.GetByGroupMemberScheduleAndLocation(groupMember, schedule.Id, locationId);

                if (groupMemberAssignment == null)
                {
                    groupMemberAssignment = new GroupMemberAssignment();
                }

                // In case there is already a group member assignment.
                else
                {
                    return(ActionBadRequest("You are already assigned to this schedule."));
                }

                groupMemberAssignment.GroupMemberId = groupMember.Id;
                groupMemberAssignment.ScheduleId    = schedule.Id;
                groupMemberAssignment.LocationId    = locationId;

                groupMemberAssignmentService.Add(groupMemberAssignment);

                // Add the group member to the service.
                rockContext.SaveChanges();

                return(ActionOk());
            }
        }
        public BlockActionResult DeleteSpecificAssignmentSchedule(Guid groupGuid, Guid scheduleGuid, Guid?locationGuid)
        {
            using (var rockContext = new RockContext())
            {
                var groupMemberAssignmentService = new GroupMemberAssignmentService(rockContext);
                var group       = new GroupService(rockContext).GetNoTracking(groupGuid);
                var groupMember = GetGroupMemberRecord(rockContext, group.Id, CurrentPersonId);

                var schedule = new ScheduleService(rockContext).GetNoTracking(scheduleGuid);

                int?locationId = null;
                if (locationGuid != null)
                {
                    var location = new LocationService(rockContext).GetNoTracking(locationGuid.Value);

                    if (location != null)
                    {
                        locationId = location.Id;
                    }
                }

                var groupMemberAssignment = groupMemberAssignmentService.GetByGroupMemberScheduleAndLocation(groupMember, schedule.Id, locationId);

                if (groupMemberAssignment == null)
                {
                    return(ActionNotFound());
                }

                if (groupMemberAssignmentService.CanDelete(groupMemberAssignment, out var errorMessage))
                {
                    groupMemberAssignmentService.Delete(groupMemberAssignment);
                    rockContext.SaveChanges();
                    return(ActionOk());
                }

                return(ActionBadRequest());
            }
        }
        /// <summary>
        /// Gets a list of assignment schedules.
        /// </summary>
        /// <param name="groupId"></param>
        /// <returns>A list of <see cref="AssignmentScheduleAndLocationBag"/> used to display on the preference page.</returns>
        private List <AssignmentScheduleAndLocationBag> GetAssignmentScheduleList(int?groupId)
        {
            using (var rockContext = new RockContext())
            {
                var groupMember = GetGroupMemberRecord(rockContext, groupId.Value, CurrentPersonId);

                if (groupMember == null)
                {
                    return(null);
                }

                var groupLocationService = new GroupLocationService(rockContext);

                var qryGroupLocations = groupLocationService
                                        .Queryable()
                                        .Where(g => g.GroupId == groupId);

                var groupMemberAssignmentService = new GroupMemberAssignmentService(rockContext);
                var groupMemberAssignmentQuery   = groupMemberAssignmentService
                                                   .Queryable()
                                                   .AsNoTracking()
                                                   .Where(x =>
                                                          x.GroupMemberId == groupMember.Id &&
                                                          (
                                                              !x.LocationId.HasValue ||
                                                              qryGroupLocations.Any(gl => gl.LocationId == x.LocationId && gl.Schedules.Any(s => s.Id == x.ScheduleId))
                                                          ));

                // Calculate the Next Start Date Time based on the start of the week so that schedule columns are in the correct order.
                var occurrenceDate = RockDateTime.Now.SundayDate().AddDays(1);

                var groupMemberAssignmentList = groupMemberAssignmentQuery
                                                .Include(a => a.Schedule)
                                                .Include(a => a.Location)
                                                .AsNoTracking()
                                                .ToList()
                                                .OrderBy(a => a.Schedule.Order)
                                                .ThenBy(a => a.Schedule.GetNextStartDateTime(occurrenceDate))
                                                .ThenBy(a => a.Schedule.Name)
                                                .ThenBy(a => a.Schedule.Id)
                                                .ThenBy(a => a.LocationId.HasValue ? a.Location.ToString(true) : string.Empty)
                                                .ToList();

                List <AssignmentScheduleAndLocationBag> assignmentScheduleAndLocations = new List <AssignmentScheduleAndLocationBag>();

                // Loop through each assignment in the list.
                foreach (var groupMemberAssignment in groupMemberAssignmentList)
                {
                    var scheduleListItem = new ListItemViewModel
                    {
                        Value = groupMemberAssignment.Schedule.Guid.ToStringSafe(),
                        Text  = groupMemberAssignment.Schedule.Name
                    };

                    var locationListItem = new ListItemViewModel
                    {
                        Value                       = groupMemberAssignment.Location != null?groupMemberAssignment.Location.Guid.ToStringSafe() : string.Empty,
                                               Text = groupMemberAssignment.Location != null ? groupMemberAssignment.Location.Name : "No Location Preference"
                    };

                    assignmentScheduleAndLocations.Add(new AssignmentScheduleAndLocationBag
                    {
                        GroupMemberAssignmentGuid = groupMemberAssignment.Guid,
                        ScheduleListItem          = scheduleListItem,
                        LocationListItem          = locationListItem
                    });
                }

                return(assignmentScheduleAndLocations);
            }
        }