public ActionResult Beta(Subscription sub)
        {
            // Validate the email address
            try
            {
                MailAddress validateEmail = new MailAddress(sub.Email);
            } catch (Exception)
            {
                return PartialView("AlertMessage", new AlertMessage("Oops!", "That isn't a valid email address.", AlertType.Error));
            }

            // Make sure this isn't a duplicate entry and add it to the database
            using (RaveRadarContext _db = new RaveRadarContext())
            {
                if (_db.Subscriptions.Any(s => String.Compare(s.Email, sub.Email, true) == 0))
                {
                    return PartialView("AlertMessage", new AlertMessage("Uh Oh!", "The email you entered is already signed up for updates.", AlertType.Error));
                }
                else
                {
                    _db.Subscriptions.Add(sub);
                    _db.SaveChanges();
                    return PartialView("AlertMessage", new AlertMessage("Done!", "Thank you for your interest in Rave Radar. We'll let you know when it's ready for you.", AlertType.Success));
                }
            }
        }
        // GET api/Sync
        public int Get()
        {
            IList<RaveDetails> uncachedEvents = new List<RaveDetails>();
              using (RaveRadarContext _db = new RaveRadarContext())
              {
            List<Owner> owners = GetTrustedOwners(_db).ToList();
            IDictionary<Int64, DateTime> cachedEventsDictionary = _db.Raves.Where(r => r.StartTime >= DateTime.Now).ToDictionary(r => r.RaveID, r => r.UpdateTime);
            IDictionary<Int64, DateTime> fbActiveEvents = FQLToObjectsHelper.GetActiveEventIDsByOwner(owners); // Add submitted events to this collection

            // Decide which of the active events need to be cached
            IList<Int64> uncachedIds = new List<Int64>();
            IList<Int64> cachedIds = new List<Int64>();
            foreach (Int64 Id in fbActiveEvents.Keys)
            {
              if (!cachedEventsDictionary.ContainsKey(Id) || (fbActiveEvents[Id] > cachedEventsDictionary[Id]))
              {
            uncachedIds.Add(Id);
              }
              else
              {
            cachedIds.Add(Id);
              }
            }
            // TODO: Don't forget to eventually integrate events without trusted owners
            //  - Query DB raves for all submitted raves

            // Get uncached events
            uncachedEvents = FQLToObjectsHelper.GetRaveDetailsFromEventIDs(uncachedIds);

            // Cache the events
            _db.UpsertRaveDetails(uncachedEvents, _db);
              }

              return uncachedEvents.Count;
        }
        private static IList<Owner> GetTrustedOwners()
        {
            IList<Owner> owners;
            using (RaveRadarContext _db = new RaveRadarContext())
            {
            owners = GetTrustedOwners(_db).ToList();
            }

            return owners;
        }
        private IList<RavePin> GetRavePins(FacetCollection<Rave> facets)
        {
            IList<RavePin> results = new List<RavePin>();
            using (RaveRadarContext _db = new RaveRadarContext())
            {
                IQueryable<Rave> filteredRaves = _db.Raves.AsQueryable();
                if (facets != null)
                {
                    filteredRaves = facets.Filter(filteredRaves);
                }

                results = (from r in filteredRaves
                          join v in _db.Venues on r.VenueID equals v.VenueID
                          orderby r.StartTime
                          select new RavePin
                              {
                                  ID = r.ID,
                                  PicURL = r.PicURL ?? string.Empty,
                                  Location = r.Location,
                                  Latitude = v.Latitude,
                                  Longitude = v.Longitude,
                              }).ToList();
            }

            return results;
        }
        private IList<RavePinInfo> GetRavePinInfo(IList<Int64> ids)
        {
            IList<RavePinInfo> results = new List<RavePinInfo>();
            using (RaveRadarContext _db = new RaveRadarContext())
            {
                results = (from r in _db.Raves
                           where ids.Contains(r.ID)
                           join o in _db.Owners on r.OwnerID equals o.OwnerID
                           select new RavePinInfo
                           {
                               ID = r.ID,
                               Name = r.Name.Length > 41 ? String.Concat(r.Name.Substring(0, 38).TrimEnd(), "...") : r.Name,
                               RaveID = r.RaveID,
                               VenueID = r.VenueID,
                               OwnerID = r.OwnerID,
                               Location = r.Location,
                               OwnerName = o.Name,
                               PicURL = r.PicURL,
                               StartTime = r.StartTime,
                               EndTime = r.EndTime,
                               IsDateOnly = r.IsDateOnly
                           }).OrderBy(r => r.Location).ThenBy(r => r.StartTime).ToList();
            }

            for (int i = 0; i < results.Count; i++)
            {
                string dateText, timeText;
                GetEventDateText(results[i].StartTime, results[i].EndTime, results[i].IsDateOnly, out dateText, out timeText);
                results[i].DateText = dateText;
                results[i].TimeText = timeText;
            }

            return results;
        }
        private IList<ClusterPinInfo> GetClusterPinInfo(IList<Int64> ids)
        {
            IList<ClusterPinInfo> results = new List<ClusterPinInfo>();

            using (RaveRadarContext _db = new RaveRadarContext())
            {
                results = (from r in _db.Raves
                           join v in _db.Venues on r.VenueID equals v.VenueID
                           where r.VenueID != null && ids.Contains(r.ID)
                           select new ClusterPinInfo {
                                VenueID = v.VenueID,
                                PicURL = v.PicURL,
                           }).Distinct().ToList();

                foreach (ClusterPinInfo cluster in results)
                {
                    cluster.Raves = _db.Raves.Where(r => r.VenueID == cluster.VenueID && ids.Contains(r.ID)).Distinct().OrderBy(r => r.StartTime).Select(r => new RaveMeta
                                    {
                                        ID = r.ID,
                                        RaveID = r.RaveID,
                                        PicURL = r.PicURL
                                    }).ToList();
                    cluster.Location = _db.Raves.Where(r => r.VenueID == cluster.VenueID && ids.Contains(r.ID)).Select(r => r.Location).FirstOrDefault();
                }
            }

            return results;
        }
        public ActionResult Popover(string ids)
        {
            IList<Int64> parsedIds = ParseIDsFromString(ids);
            if (parsedIds.Count > 1)
            {
                bool multipleVenues = false;
                using (RaveRadarContext _db = new RaveRadarContext())
                {
                    multipleVenues = _db.Raves.Where(r => parsedIds.Contains(r.ID)).Select(r => r.Location).Distinct().Count() > 1;
                }

                if (multipleVenues)
                {
                    // TODO: Return exact data to be consumed
                    IList<ClusterPinInfo> results = GetClusterPinInfo(parsedIds);
                    return PartialView("ClusterPopover", results);
                }
                else
                {
                    // TODO: Return exact data to be consumed
                    IList<RavePinInfo> results = GetRavePinInfo(parsedIds);
                    return PartialView("VenuePopover", results);
                }

            }
            else if (parsedIds.Count > 0)
            {
                // TODO: Return exact data to be consumed
                RavePinInfo result = GetRavePinInfo(parsedIds).First();
                return PartialView("EventPopover", result);
            }

            AlertMessage error = new AlertMessage("Uh oh!", "We couldn't find the event.", AlertType.Error, false);
            return PartialView("AlertMessage", error);
        }
        public static IList<RaveDetails> GetRaveDetailsFromEventIDs(IEnumerable<Int64> eventIds)
        {
            _fb.AccessToken = _GenericAccessToken;

            string fields = "eid, name, pic_square, start_time, end_time, is_date_only, creator, update_time, location, venue";
            string eidList = string.Join(",", eventIds.ToArray());
            dynamic fqlResult = _fb.Get("fql", new { q = String.Format("SELECT {0} FROM event WHERE eid IN ({1})", fields, eidList) });
            JsonArray fqlEventResults = fqlResult.data;

            IList<RaveDetails> eventResults = new List<RaveDetails>();
            HashSet<Venue> venueResults = new HashSet<Venue>();
            HashSet<Rave> raveResults = new HashSet<Rave>();
            foreach (dynamic fqlEvent in fqlEventResults)
            {
                Int64? creatorId = fqlEvent.creator ?? 0;
                Int64? eventId = fqlEvent.eid;
                Int64? venueId = 0;
                if (fqlEvent.venue.Count > 0)
                {
                     dynamic jsonVenue = (JsonObject)fqlEvent.venue;
                     venueId = jsonVenue.id ?? 0;
                }

                Rave aRave = null;
                Venue aVenue = null;
                Owner aOwner = null;
                if (eventId != null)
                {
                    // Get the owner; no chance for duplications
                    aOwner = GetRaveOwnerFromUserID(creatorId);

                    // Before querying for the Venue, make sure we haven't already queried it
                    if (venueResults.Any(v => v.VenueID == venueId))
                    {
                        aVenue = venueResults.First(v => v.VenueID == venueId);
                    }
                    else if (fqlEvent.venue.Count > 0)
                    {
                        aVenue = GetVenueFromJsonObject((JsonObject)fqlEvent.venue);
                        if (aVenue == null)
                        {
                          // If no facebook page exists for this Venue, create a new negative ID
                          // All negative ID's therefore show that the Venue does not exist on Facebook
                                                    aVenue = new Venue();
                          using (RaveRadarContext _db = new RaveRadarContext())
                          {
                              long dbMin = _db.Venues.Min(v => v.VenueID).GetValueOrDefault(0);
                              long syncMin = venueResults.Min(v => v.VenueID).GetValueOrDefault(0);
                              aVenue.VenueID = (dbMin <= syncMin ? dbMin : syncMin) - 1;
                                                            aVenue.Name = fqlEvent.location ?? string.Empty;
                                                            aVenue.GetLocationFromGoogle(fqlEvent.location ?? string.Empty);

                                                            // If no location found, reset venue to null
                                                            if (aVenue.GetLocation() == null)
                                                            {
                                                                aVenue = null;
                                                            }
                          }
                        }

                                                if (aVenue != null)
                                                {
                                                    venueResults.Add(aVenue);
                                                }
                    }

                    // Before querying for the Rave, make sure we haven't already queried it
                    if (raveResults.Any(r => r.RaveID == eventId))
                    {
                        aRave = raveResults.First(r => r.RaveID == eventId);
                    }
                    else
                    {
                        aRave = new Rave();
                        aRave.RaveID = eventId ?? 0; // Should never happen
                        aRave.OwnerID = aOwner.OwnerID;
                        if (aVenue == null) { aRave.VenueID = null; } else { aRave.VenueID = aVenue.VenueID; }
                        aRave.Name = fqlEvent.name ?? string.Empty;
                        aRave.PicURL = fqlEvent.pic_square ?? ConfigurationManager.AppSettings["DefaultRaveIcon"].ToString();

                        aRave.StartTime = ConvertFacebookDateToLocal(fqlEvent.start_time, fqlEvent.is_date_only);
                        if (fqlEvent.end_time == null) { aRave.EndTime = null; }
                        else { aRave.EndTime = ConvertFacebookDateToLocal(fqlEvent.end_time, fqlEvent.is_date_only); }
                        aRave.IsDateOnly = fqlEvent.is_date_only;
                        aRave.Location = fqlEvent.location ?? string.Empty;
                        aRave.IsApproved = (aOwner == null ? false : aOwner.IsTrusted);
                        aRave.SubmitterID = null;
                        aRave.UpdateTime = DateTimeConvertor.FromUnixTime((double)fqlEvent.update_time);
                        raveResults.Add(aRave);
                    }
                }

                // Put all the details together to create one object
                eventResults.Add(new RaveDetails(aRave, aOwner, aVenue));
            }

            return eventResults;
        }
        public static Owner GetRaveOwnerFromUserID(Int64? userId)
        {
            Owner ownerResult = null;
            using (RaveRadarContext _db = new RaveRadarContext())
            {
                ownerResult = _db.Owners.Single(o => o.OwnerID == userId);
            }

            return ownerResult;
        }
 private static IQueryable<Owner> GetTrustedOwners(RaveRadarContext _db)
 {
     return _db.Owners.Where(o => o.IsTrusted).Distinct();
 }