/// <summary>
        /// Generates notifications for new Medical Appointments
        /// </summary>
        private static void GenerateNotificationsForNewMedicalAppointments(
            [NotNull] CerebelloEntities db, DateTime referenceTime, [NotNull] ICollection <Tuple <Notification, object> > notificationsToBeDispatched)
        {
            if (db == null)
            {
                throw new ArgumentNullException("db");
            }
            if (notificationsToBeDispatched == null)
            {
                throw new ArgumentNullException("notificationsToBeDispatched");
            }

            // check for appointments that have to be notified
            var timeOffset             = referenceTime.AddMinutes(10);
            var unnotifiedAppointments =
                db.Appointments.Where(
                    a => !a.Notified && a.Type == (int)TypeAppointment.MedicalAppointment && a.Start >= referenceTime && a.Start < timeOffset).ToList();

            foreach (var appointment in unnotifiedAppointments)
            {
                Debug.Assert(appointment.PatientId != null, "appointment.PatientId != null");

                var medicalAppointmentData = new MedicalAppointmentNotificationData
                {
                    PatientId     = appointment.PatientId.Value,
                    PatientName   = appointment.Patient.Person.FullName,
                    DoctorName    = appointment.Patient.Doctor.Users.First().Person.FullName,
                    DoctorId      = appointment.Patient.DoctorId,
                    AppointmentId = appointment.Id,
                    Time          = DateTimeHelper.GetFormattedTime(
                        PracticeController.ConvertToLocalDateTime(appointment.Practice, appointment.Start)),
                    PracticeIdentifier = appointment.Practice.UrlIdentifier,
                    DoctorIdentifier   = appointment.Doctor.UrlIdentifier
                };

                var medicalAppointmentDataString = new JavaScriptSerializer().Serialize(medicalAppointmentData);

                // for each secretary, I need to create a new notification
                foreach (var user in appointment.Practice.Users.Where(user => user.Secretary != null))
                {
                    var newNotification = new Notification()
                    {
                        CreatedOn  = referenceTime,
                        IsClosed   = false,
                        UserToId   = user.Id,
                        Type       = NotificationConstants.MEDICAL_APPOINTMENT_NOTIFICATION_TYPE,
                        PracticeId = appointment.PracticeId,
                        Data       = medicalAppointmentDataString
                    };

                    user.Notifications.Add(newNotification);
                    notificationsToBeDispatched.Add(new Tuple <Notification, object>(newNotification, medicalAppointmentData));
                }

                appointment.Notified = true;
            }
            db.SaveChanges();
        }
        /// <summary>
        /// Generates notifications for new Medical Appointments
        /// </summary>
        private static void GenerateNotificationsForNewGenericAppointments(
            [NotNull] CerebelloEntities db, DateTime referenceTime, [NotNull] ICollection <Tuple <Notification, object> > notificationsToBeDispatched)
        {
            if (db == null)
            {
                throw new ArgumentNullException("db");
            }
            if (notificationsToBeDispatched == null)
            {
                throw new ArgumentNullException("notificationsToBeDispatched");
            }

            // check for appointments that have to be notified
            var timeOffset             = referenceTime.AddMinutes(30);
            var unnotifiedAppointments =
                db.Appointments.Where(
                    a => !a.Notified && a.Type == (int)TypeAppointment.GenericAppointment && a.Start >= referenceTime && a.Start < timeOffset).ToList();

            foreach (var appointment in unnotifiedAppointments)
            {
                Debug.Assert(appointment.PatientId != null, "appointment.PatientId != null");

                var genericAppointmentData = new GenericAppointmentNotificationData()
                {
                    Text = appointment.Description,
                    Time = DateTimeHelper.GetFormattedTime(
                        PracticeController.ConvertToLocalDateTime(appointment.Practice, appointment.Start))
                };

                var genericAppointmentDataString = new JavaScriptSerializer().Serialize(genericAppointmentData);

                // notify the doctor
                var newNotification = new Notification()
                {
                    CreatedOn  = referenceTime,
                    IsClosed   = false,
                    UserToId   = appointment.DoctorId,
                    Type       = NotificationConstants.GENERIC_APPOINTMENT_NOTIFICATION_TYPE,
                    PracticeId = appointment.PracticeId,
                    Data       = genericAppointmentDataString
                };

                appointment.Doctor.Users.First().Notifications.Add(newNotification);
                notificationsToBeDispatched.Add(new Tuple <Notification, object>(newNotification, genericAppointmentData));

                appointment.Notified = true;
            }
            db.SaveChanges();
        }
        private static PatientViewModel GetViewModel(PracticeController controller, [NotNull] Patient patient, bool includeSessions, bool includeFutureAppointments, bool includeAddressData = true)
        {
            if (patient == null) throw new ArgumentNullException("patient");

            // Person, address, and patient basic properties.
            var viewModel = new PatientViewModel();

            FillPersonViewModel(controller.DbPractice, patient.Person, viewModel);

            viewModel.Id = patient.Id;
            viewModel.Code = patient.Code.HasValue ? patient.Code.Value.ToString("D6") : "000000";
            viewModel.PatientId = patient.Id;
            viewModel.PersonId = patient.Person.Id;
            viewModel.Observations = patient.Person.Observations;

            if (includeAddressData)
            {
                var address = patient.Person.Addresses.SingleOrDefault();
                viewModel.Address = address != null ? GetAddressViewModel(address) : new AddressViewModel();
            }

            // Other (more complex) properties.

            if (includeFutureAppointments)
            {
                // gets a textual date. The input date must be LOCAL
                Func<DateTime, string> getRelativeDate = s =>
                {
                    var result = s.ToShortDateString();
                    result += ", " + DateTimeHelper.GetFormattedTime(s);
                    result += ", " +
                              DateTimeHelper.ConvertToRelative(s, controller.GetPracticeLocalNow(),
                                                               DateTimeHelper.RelativeDateOptions.IncludeSuffixes |
                                                               DateTimeHelper.RelativeDateOptions.IncludePrefixes |
                                                               DateTimeHelper.RelativeDateOptions.ReplaceToday |
                                                               DateTimeHelper.RelativeDateOptions.ReplaceYesterdayAndTomorrow);

                    return result;
                };

                // get appointments scheduled for the future
                var utcNow = controller.GetUtcNow();

                var appointments = patient.Appointments
                    .Where(
                        a => a.DoctorId == patient.DoctorId
                             && a.Start > utcNow)
                    .ToList();

                viewModel.FutureAppointments = (from a in appointments
                                                select new AppointmentViewModel
                                                {
                                                    PatientId = a.PatientId,
                                                    PatientName = a.PatientId != default(int) ? a.Patient.Person.FullName : null,
                                                    LocalDateTime = ConvertToLocalDateTime(controller.DbPractice, a.Start),
                                                    LocalDateTimeSpelled = getRelativeDate(ConvertToLocalDateTime(controller.DbPractice, a.Start))
                                                }).ToList();
            }

            if (includeSessions)
            {
                var sessions = GetSessionViewModels(controller.DbPractice, patient, null);

                viewModel.Sessions = sessions;
            }

            return viewModel;
        }