public async Task <IEnumerable <DomainEvent> > GetEventsByDateAsync(int userId, DateTime date)
        {
            Expression <Func <Event, bool> > filter = e => e.Calendars.Any(c => c.Calendar.OwnerId == userId) &&
                                                      ((e.Period == null && date >= e.StartDate.Value && date <= e.EndDate.Value) ||
                                                       (e.Period != null && date >= e.Period.PeriodStart && date <= e.Period.PeriodEnd));


            var dataEvents = (await _eventRepository.FindAllIncludingAsync(e => e.Period, e => e.Calendars))
                             .Where(filter)
                             .ToList();

            dataEvents.RemoveAll(e => e.IsPrivate && e.OwnerId != userId);

            var domainEvents   = _mapper.Map <List <DomainEvent> >(dataEvents);
            var filteredEvents = domainEvents.Where(e => e.Period == null).ToList();

            foreach (var e in domainEvents.Where(e => e.Period != null))
            {
                var calc = new RecurrenceCalculator(e);
                var rec  = calc.GetRecurrences();
                filteredEvents.AddRange(rec);
            }

            filteredEvents = filteredEvents.Where(e => EFFunctions.DateDiffDay(date, e.StartDate.Value) >= 0 && EFFunctions.DateDiffDay(date, e.EndDate.Value) <= 0).ToList();

            return(filteredEvents.OrderBy(e => e.StartDate.Value.AddMinutes(e.StartTime?.TotalMinutes ?? 0)));
        }
        public async Task <IEnumerable <EventUser> > GetEventsToNotifyAsync(DateTime dateTime)
        {
            dateTime = dateTime.AddSeconds(-dateTime.Second);
            var dateDate = dateTime.Date;

            Expression <Func <EventCalendar, bool> > filter = e => e.Event.RemindBefore != null &&
                                                              ((e.Event.Period != null && dateDate >= e.Event.Period.PeriodStart && dateDate <= e.Event.Period.PeriodEnd) ||
                                                               (e.Event.Period == null && !e.Event.IsAllDay && EFFunctions.DateDiffMinute(e.Event.StartDate.Value.AddMinutes(e.Event.StartTime.Value.TotalMinutes).AddMinutes(-e.Event.RemindBefore.Value), dateTime) == 0) ||
                                                               (e.Event.Period == null && e.Event.IsAllDay && EFFunctions.DateDiffHour(dateTime, e.Event.StartDate.Value.AddMinutes(-e.Event.RemindBefore.Value)) <= 24));

            var eventCalendars = (await _eventCalendarRepository.FindAllIncludingAsync(e => e.Calendar, e => e.Calendar.Owner, e => e.Calendar.SharedUsers,
                                                                                       e => e.Event, e => e.Event.Period))
                                 .Where(filter)
                                 .AsNoTracking()
                                 .ToList();

            if (!eventCalendars.Any())
            {
                return(null);
            }

            var domainEventCalendars = _mapper.Map <List <DomainEventCalendar> >(eventCalendars);

            domainEventCalendars = CalculateRecurrences(domainEventCalendars)
                                   .Where(e => (!e.Event.IsAllDay && EFFunctions.DateDiffMinute(dateTime, e.Event.StartDate.Value.Add(e.Event.StartTime.Value).AddMinutes(-e.Event.RemindBefore.Value)) == 0) ||
                                          (e.Event.IsAllDay && EFFunctions.DateDiffMinute(e.Calendar.Owner.TimeZone.ConvertFromUtc(dateTime), e.Event.StartDate.Value.AddMinutes(-e.Event.RemindBefore.Value)) == 0))
                                   .ToList();

            if (!domainEventCalendars.Any())
            {
                return(null);
            }

            var eventUsers = domainEventCalendars.SelectMany(e => e.Calendar.SharedUsers.Where(u => u.IsSubscribed).Select(c => new EventUser
            {
                Event = e.Event,
                User  = c.User
            })).ToList();

            var owners = domainEventCalendars.Select(e => new EventUser
            {
                Event = e.Event,
                User  = e.Calendar.Owner
            });

            eventUsers.AddRange(owners);

            return(eventUsers);
        }