protected override void UpdateEntity(HappeningUser entity, InvitationDto dto)
        {
            entity.Update(Enum.Parse <RSVP>(dto.Status, true), dto.ReminderXMinsBefore, dto.IsPrivate);


            Reminder reminder = entity.Reminder;

            // fetch if necessary
            if (reminder == null)
            {
                reminder = reminderService.GetEnt(entity.ReminderId.Value);
            }

            reminder.Update(dto.Date.AddMinutes(entity.ReminderXMinsBefore * -1), dto.Date, reminder.IsSilenced);
        }
        public IEnumerable <IEnumerable <HappeningDto> > Get(CalendarSearchFilterDto filter)
        {
            // finding out whether the filter is asking for the logged in user or another user effects permissions
            User currentUser = loginService.GetCurrentUser();

            // although UserId == null is a different case which doesn't need the same direct permissions check
            bool isCurrentUser = filter.UserId != null && filter.UserId.Value == loginService.GetCurrentUserId(true).Value;

            if (!isCurrentUser && filter.UserId != null)
            {
                User user = userService.GetEnt(filter.UserId.Value);

                // in all cases the filters will restrict private data from being shown, but an error is good feedback for a faulty case
                // without this, they'd just get 0
                if (!user.CalendarVisibleToOthers && currentUser.Role != UserRole.Admin)
                {
                    throw new HandledException(new ArgumentException("Can't view calendar for user set to private"));
                }
            }

            IEnumerable <HappeningDto> data = GetQueryable().Where(x => (filter.UserId == null || (x.AllUsers.Select(y => y.UserId).Contains(filter.UserId.Value) &&
                                                                                                   (x.AllUsers.FirstOrDefault(y => filter.UserId.Value == y.UserId).User.CalendarVisibleToOthers ||
                                                                                                    x.AllUsers.FirstOrDefault(y => filter.UserId.Value == y.UserId).User.Id == currentUser.Id ||
                                                                                                    currentUser.Role == UserRole.Admin)
                                                                                                   )) &&
                                                                   ((isCurrentUser || currentUser.Role == UserRole.Admin) || !x.IsPrivate) &&
                                                                   (               // this complex part captures whether either the start or end time of the event is contained within the search range
                                                                       (
                                                                           (filter.StartDate == null || x.StartTime >= filter.StartDate.Value) &&
                                                                           (filter.EndDate == null || x.StartTime <= filter.EndDate.Value)
                                                                       )
                                                                       ||
                                                                       (
                                                                           (filter.StartDate == null || x.EndTime >= filter.StartDate.Value) &&
                                                                           (filter.EndDate == null || x.EndTime <= filter.EndDate.Value)
                                                                       )
                                                                   )
                                                                   ).OrderBy(x => x.StartTime)
                                              .Select(x => DtoFromEntityWithUserData(x, filter.UserId ?? currentUser.Id));

            if (filter.TextualDisplay)
            {
                List <IEnumerable <HappeningDto> > result = new List <IEnumerable <HappeningDto> >();
                result.Add(data);
                return(result);
            }
            else
            {
                // if Calendar mode, must have startDate/endDate set
                if (filter.StartDate == null || filter.EndDate == null || filter.StartDate.Value.Month != filter.EndDate.Value.Month)
                {
                    throw new HandledException(new ArgumentException("Start and End Date filters must be set, and be within the same month, when textual display is false"));
                }

                int days = DateTime.DaysInMonth(filter.StartDate.Value.Year, filter.StartDate.Value.Month);

                List <HappeningDto>[] result = new List <HappeningDto> [days];
                // intialize all lists
                for (int x = 0; x < result.Length; x++)
                {
                    result[x] = new List <HappeningDto>();
                }

                // return empty set if no data/rows
                if (data.Count() == 0)
                {
                    return(result);
                }

                IEnumerable <HappeningDto> sortedData = data.OrderBy(x => x.StartTime);



                // since start and end dates can extend beyond the month the calculations can get a little complicated
                int currentMonth = filter.StartDate.Value.Month;
                int currentYear  = filter.StartDate.Value.Year;

                DateTime earliestStart = sortedData.Select(x => x.StartTime).OrderBy(x => x).First();
                DateTime latestEnd     = sortedData.Select(x => x.EndTime).OrderBy(x => x).Last();

                // start and end end range offset by -1 to match array notation

                int startDay = earliestStart.Month == currentMonth && earliestStart.Year == currentYear ? earliestStart.Day : 1;
                int endDay   = latestEnd.Month == currentMonth && latestEnd.Year == currentYear ? latestEnd.Day : days;

                for (int x = startDay; x <= endDay; x++)
                {
                    DateTime date = new DateTime(currentYear, currentMonth, x);
                    Func <DateTime, DateTime> dateFlatten = (DateTime input) => new DateTime(input.Year, input.Month, input.Day);

                    // find all happenings that are occuring on at least the particular day
                    IEnumerable <HappeningDto> relevantRows = sortedData.Where(i => date >= dateFlatten(i.StartTime) && date <= dateFlatten(i.EndTime));
                    result[x - 1].AddRange(relevantRows); // days are 1 aligned, we have to -1 to convert to array positions which are 0 aligned
                }

                return(result);
            }
        }