public HttpResponseMessage CheckIn(PatronViewModel checkIn)
        {
            ApiResponse response = new ApiResponse(Request);
            if (checkIn == null)
            {
                response.errors.Add(new NullRequest());
                return response.GenerateResponse(HttpStatusCode.BadRequest);
            }
            try
            {
                using (var database = new Database())
                {
                    var volunteerName = Request.Headers.GetHeaderValue("username");
                    var volunteer = database.Volunteers.FirstOrDefault(v => v.Username == volunteerName);
                    var serviceType = database.ServiceTypes.FirstOrDefault(st => st.ID == checkIn.ServiceSelection);
                    Patron patron;
                    if (checkIn.ID > -1)
                    {
                        patron = database.Patrons
                            .Include(p => p.Gender)
                            .Include(p => p.Addresses)
                            .Include(p => p.EmergencyContacts)
                            .Include(p => p.Ethnicity)
                            .Include(p => p.MaritalStatus)
                            .Include(p => p.PhoneNumbers)
                            .Include(p => p.ResidenceStatus)
                            .First(p => p.ID == checkIn.ID);
                        patron.Addresses = checkIn.Addresses;
                        patron.EmergencyContacts = checkIn.EmergencyContacts;
                        patron.PhoneNumbers = checkIn.PhoneNumbers;
                    }
                    else
                    {
                        patron = JsonConvert.DeserializeObject<Patron>(JsonConvert.SerializeObject(checkIn)); //You can move values up an inheritance chain!
                    }
                    patron.Ethnicity = database.Ethnicities.FirstOrDefault(et => et.ID == (int)checkIn.ethnicityID);
                    patron.Gender = database.Genders.FirstOrDefault(gt => gt.ID == (int)checkIn.genderID);
                    patron.ResidenceStatus = database.ResidenceStatuses.FirstOrDefault(rt => rt.ID == (int)checkIn.residenceStatusID);
                    patron.MaritalStatus = database.MaritalStatuses.FirstOrDefault(mt => mt.ID == (int)checkIn.maritalStatusID);

                    database.Patrons.AddOrUpdate(patron);
                    database.SaveChanges();
                    Visit visit = new Visit
                    {
                        CreateVolunteer = volunteer,
                        Service = serviceType,
                        Patron = patron
                    };
                    database.Visits.Add(visit);
                    database.SaveChanges();
                    return response.GenerateResponse(HttpStatusCode.Created);
                }
            }
            catch(Exception e)
            {
                response.errors.Add(new InvalidCheckIn { source = e });
                return response.GenerateResponse(HttpStatusCode.BadRequest);
            }
        }
 public static Volunteer[] GetTestVolunteers(Database context)
 {
     return context.Volunteers.ToArray()
         .Where(
             v => v.Username == testAdmin.Username ||
             v.Username == testUser.Username
         ).ToArray();
 }
        public static void Seed(Database context)
        {
            var tempUser = context.Volunteers.FirstOrDefault(v => v.Username == testUser.Username);
            var tempAdmin = context.Volunteers.FirstOrDefault(v => v.Username == testAdmin.Username);
            if (tempUser != null && tempAdmin != null) return;

            testUser.ServiceTypes = new List<ServiceType>
            {
                context.ServiceTypes.First(st => st.ID == (int) ServiceTypeID.Dental)
            };
            testAdmin.ServiceTypes = new List<ServiceType>();
            context.ServiceTypes.ToList().ForEach(st => testAdmin.ServiceTypes.Add(st));
            context.Volunteers.AddOrUpdate(
                testUser,
                testAdmin
            );

            context.SaveChanges();
        }
        public HttpResponseMessage GetPatronData(ReportingPatronViewModel reportingParams)
        {
            using (var db = new Database())
              {
            var response = new ApiResponse(Request);
            try
            {
              var servicesWanted = reportingParams.ServiceTypeSelections.Select(st => st.ID).ToArray();
              var services = db.Visits
            .Include(v => v.Patron)
            .Include(v => v.Service.ID)
            .Where(v => v.Patron.ID == reportingParams.ID && servicesWanted.Contains(v.Service.ID))
            .ToList();

              response.data = services;
              return response.GenerateResponse(HttpStatusCode.OK);
            }
            catch (Exception e)
            {
              response.errors.Add(new DatabaseFailure(e));
              return response.GenerateResponse(HttpStatusCode.InternalServerError);
            }
              }
        }
        public static AuthorizationResult Authorize(HttpRequestMessage request, RoleID[] roles)
        {
            string authToken = request.Headers.GetHeaderValue("authToken");
              string activeUser = request.Headers.GetHeaderValue("username");

              if (!string.IsNullOrEmpty(authToken) && !string.IsNullOrEmpty(activeUser))
              {
            using (var database = new Database())
            {
              var decodedAuthToken = Authorization.DecodeToken(authToken);
              if (decodedAuthToken == null)
            return AuthorizationResult.InvalidToken;

              if (decodedAuthToken.username != activeUser)
            return AuthorizationResult.MismatchedUser;

              if (decodedAuthToken.timeDiff > AuthorizationOptions.AuthTokenTimeout)
            return AuthorizationResult.ExpiredToken;

              //Valid token, need to check roles
              var dbRoles = database.RoleVolunteers
              .Where(rv => rv.Volunteer.Username == activeUser)
              .Include(rv => rv.Volunteer)
              .Select(rv => rv.Role.ID).ToArray();

              if (roles.Select(r => (int)r).Intersect(dbRoles).Count() == roles.Length)
            return AuthorizationResult.Success;

              return AuthorizationResult.Unauthorized;
            }
              }

              return AuthorizationResult.InvalidRequest;
        }
        public HttpResponseMessage FindPatron(dynamic data)
        {
            DateTime PatronDoB = DateTime.MinValue;
            try
            {
                DateTime.TryParse(data.dateOfBirth, out PatronDoB);
            }
            catch(Exception e) { }
            Patron searchData = new Patron
            {
                FirstName = data.firstName,
                MiddleName = data.middleName,
                LastName = data.lastName,
                DateOfBirth = PatronDoB
            };
            ApiResponse response = new ApiResponse(Request);
            try
            {
                using (var patronContext = new Database())
                {
                    var patrons = patronContext.Patrons.Where(
                        p =>
                            p.FirstName.ToLower().Contains(searchData.FirstName.ToLower()) ||
                            p.MiddleName.ToLower().Contains(searchData.MiddleName.ToLower()) ||
                            p.LastName.ToLower().Contains(searchData.LastName.ToLower()) ||
                            p.DateOfBirth.ToString().Contains(searchData.DateOfBirth.ToString()))
                        .Include(p => p.MaritalStatus)
                        .Include(p => p.Ethnicity)
                        .Include(p => p.Gender)
                        .Include(p => p.ResidenceStatus)
                        .Include(p => p.EmergencyContacts)
                        .Include(p => p.PhoneNumbers)
                        .Include(p => p.Addresses)
                        .Include(p => p.Visits.Select(v => v.Service))
                    .ToList();

                    response.data = patrons;

                    return response.GenerateResponse(HttpStatusCode.OK);
                }
            }
            catch (Exception e)
            {
                response.errors.Add(new InvalidPatron { source = e });
                return response.GenerateResponse(HttpStatusCode.BadRequest);
            }
        }
        public HttpResponseMessage GetServiceData(ReportingServiceViewModel reportingParams)
        {
            ApiResponse response = new ApiResponse(Request);
              using (var db = new Database())
              {
            if (reportingParams.TimePeriod == "Today")
            {
              reportingParams.StartDate = DateTime.UtcNow.AbsoluteStart();
              reportingParams.EndDate = DateTime.UtcNow.AbsoluteEnd();
            }
            else if (reportingParams.TimePeriod == "Specific Date")
            {
              reportingParams.StartDate = reportingParams.StartDate.ToUniversalTime().AbsoluteStart();
              reportingParams.EndDate = reportingParams.StartDate.ToUniversalTime().AbsoluteEnd();
            }
            else if (reportingParams.TimePeriod == "Date Range")
            {
              reportingParams.StartDate = reportingParams.StartDate.ToUniversalTime().AbsoluteStart();
              reportingParams.EndDate = reportingParams.EndDate.ToUniversalTime().AbsoluteEnd();
            }
            else if (reportingParams.TimePeriod == "All Time")
            {
              reportingParams.StartDate = DateTime.MinValue;
              reportingParams.EndDate = DateTime.MaxValue;
            }
            else
            {
              response.errors.Add(new InvalidTimePeroid());
              return response.GenerateResponse(HttpStatusCode.BadRequest);
            }

            var serviceTypeIDs = reportingParams.ServiceTypeSelections.Select(st => st.ID).ToList();

            var report = db.Visits
            .Include(v => v.Service)
            .Include(v => v.Patron)
            .Include(v => v.Patron.ResidenceStatus)
            .Include(v => v.Patron.MaritalStatus)
            .Include(v => v.Patron.Gender)
            .Include(v => v.Patron.Ethnicity)
            .Include(v => v.Patron.Addresses)
            .Include(v => v.CreateVolunteer)
            .Where(v =>
              v.CreateDate >= reportingParams.StartDate && v.CreateDate <= reportingParams.EndDate &&
              !string.IsNullOrEmpty(reportingParams.ZipCode) ? v.Patron.Addresses.Count(a => a.Zip.Contains(reportingParams.ZipCode) || reportingParams.ZipCode.Contains(a.Zip)) > 0 : true &&
              serviceTypeIDs.Contains(v.Service.ID)
            ).ToList()
            .Select(v => new
            {
              VisitDate = v.CreateDate,
              VolunteerLastName = v.CreateVolunteer.FirstName,
              VolunteerFirstName = v.CreateVolunteer.LastName,
              PatronFirstName = v.Patron.FirstName,
              PatronMiddleName = v.Patron.MiddleName,
              PatronLastName = v.Patron.LastName,
              Service = v.Service.ServiceName,
              MaritalStatus = v.Patron.MaritalStatus.Name,
              Gender = v.Patron.Gender.Name,
              Ethnicity = v.Patron.Ethnicity.Name,
              Addresses =  string.Join(" | ", v.Patron.Addresses.Select(a => $"{a.StreetAddress} {a.City} {a.State} {a.Zip}"))
            });

            response.data = report;

            return response.GenerateResponse(HttpStatusCode.OK);
              }
        }