public HttpResponseMessage CheckIn(string sessionKey, double latitude, double longitude)
        {
            try
            {
                var context = new NationalPlacesContext();
                var user = context.Users.FirstOrDefault(u => u.SessionKey == sessionKey);
                if (user == null)
                {
                    throw new Exception("You must be logged in to check in.");
                }
                int placeId = GetNearbyPlace(latitude, longitude);
                if (placeId != 0)
                {
                    var place = context.Places.FirstOrDefault(p => p.Id == placeId);
                    place.Users.Add(user);
                    context.SaveChanges();
                    var response = this.Request.CreateResponse(HttpStatusCode.OK,
                                                               "You are checked in from: " + place.Name);
                    return response;
                }
                else
                {
                    var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                                               "You are not close to any place of the application!");
                    return response;
                }

            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
                return response;
            }
        }
 public HttpResponseMessage GetTownsAndPlaces()
 {
     try
     {
         var context = new NationalPlacesContext();
         var allTowns = from town in context.Towns
                        select new TownsAndPlacesModel()
                        {
                            Id=town.Id,
                            TownName = town.Name,
                            Places = from place in town.Places
                                     select new NationalPlaceModel()
                                                {
                                                    Id = place.Id,
                                                    Name = place.Name,
                                                    PictureUrl = place.PictureUrl,
                                                    Description = place.Description,
                                                    Town = place.Town.Name
                                                }
                        };
         var response = this.Request.CreateResponse(HttpStatusCode.OK, allTowns);
         return response;
     }
     catch (Exception ex)
     {
         var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                      ex.Message);
         return response;
     }
 }
        //[HttpGet]
        //[ActionName("nearbyPlaces")]
        public int GetNearbyPlace(double latitude, double longitude)
        {
            var context = new NationalPlacesContext();
            NationalPlaceModel nearbyPlace = new NationalPlaceModel();
            double minDistance = double.MaxValue;
            foreach (var place in context.Places)
            {
                double distance = CheckDistance(place.Latitude, place.Longitude, latitude, longitude);

                if (minDistance > distance)
                {
                    nearbyPlace.Id = place.Id;
                    minDistance = distance;
                }
            }
            //var response = this.Request.CreateResponse(HttpStatusCode.OK, nearbyPlace.Id);
            return nearbyPlace.Id;
        }
 public HttpResponseMessage GetAll()
 {
     try
     {
         var context = new NationalPlacesContext();
         var allTowns = from town in context.Towns
                        select new TownModel()
                                   {
                                       Id = town.Id,
                                       Name = town.Name,
                                       CountOfPlaces = town.Places.Count
                                   };
         var response = this.Request.CreateResponse(HttpStatusCode.OK, allTowns);
         return response;
     }
     catch(Exception ex)
     {
         var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                      ex.Message);
         return response;
     }
 }
        public HttpResponseMessage addProfilePicture(string sessionKey, string url)
        {
            try
            {
                var contex = new NationalPlacesContext();
                var user = contex.Users.FirstOrDefault(u => u.SessionKey == sessionKey);
                if (user == null)
                {
                    throw new Exception("You must be logged in to upload picture.");
                }
                user.ProfilePictureUrl = url;
                contex.SaveChanges();

                var response = this.Request.CreateResponse(HttpStatusCode.OK);
                return response;

            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message);
                return response;
            }
        }
        public HttpResponseMessage GetPictures(string sessionKey)
        {
            try
            {
                var contex = new NationalPlacesContext();
                var user = contex.Users.FirstOrDefault(u => u.SessionKey == sessionKey);
                if (user == null)
                {
                    throw new Exception("You must be logged in to get pictures.");
                }

                var pictures = from picture in user.Pictures
                               select picture.PictureUrl;

                var response = this.Request.CreateResponse(HttpStatusCode.OK, pictures);
                return response;

            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message);
                return response;
            }
        }
        public HttpResponseMessage GetPlaceDetails(int placeId)
        {
            try
            {
                var context = new NationalPlacesContext();
                var place = context.Places.FirstOrDefault(p => p.Id == placeId);
                var placeDetails = new NationalPlaceModel()
                                       {
                                           Id = place.Id,
                                           Name = place.Name,
                                           Description = place.Description,
                                           PictureUrl = place.PictureUrl,
                                           Town = place.Town.Name
                                       };

                var response = this.Request.CreateResponse(HttpStatusCode.OK, placeDetails);
                return response;
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
                return response;
            }
        }
        public HttpResponseMessage PutLogoutUser(string sessionKey)
        {
            try
            {
                var context = new NationalPlacesContext();
                using (context)
                {
                    var user = context.Users.FirstOrDefault(u => u.SessionKey == sessionKey);
                    if (user == null)
                    {
                        throw new ArgumentException("Invalid user authentication.");
                    }

                    user.SessionKey = null;
                    context.SaveChanges();

                    var response = this.Request.CreateResponse(HttpStatusCode.OK);
                    return response;
                }
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message);
                return response;
            }
        }
        public HttpResponseMessage PostRegisterUser(UserModel model)
        {
            try
            {
                var dbContext = new NationalPlacesContext();
                using (dbContext)
                {
                    this.ValidateUsername(model.Username);
                    this.ValidateName(model.Name);
                    this.ValidateAuthCode(model.AuthCode);

                    var usernameToLower = model.Username.ToLower();
                    var user = dbContext.Users.FirstOrDefault(u => u.Username.ToLower() == usernameToLower);

                    if (user != null)
                    {
                        throw new InvalidOperationException("Username is already taken!");
                    }

                    user = new NationalPlaces.Models.User()
                    {
                        Username = usernameToLower,
                        Name = model.Name,
                        AuthCode = model.AuthCode,
                        ProfilePictureUrl = model.ProfilePictureUrl

                    };

                    dbContext.Users.Add(user);
                    dbContext.SaveChanges();

                    user.SessionKey = this.GenerateSessionKey(user.Id);
                    dbContext.SaveChanges();

                    var loggedModel = new LoggedUserModel()
                    {
                        Name = user.Name,
                        SessionKey = user.SessionKey
                    };

                    var response = this.Request.CreateResponse(HttpStatusCode.Created,
                                              loggedModel);
                    return response;
                }
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                             ex.Message);
                return response;
            }
        }
        public HttpResponseMessage PostLoginUser(UserModel model)
        {
            try
            {
                ValidateUsername(model.Username);
                ValidateAuthCode(model.AuthCode);

                var context = new NationalPlacesContext();
                using (context)
                {
                    var user = context.Users.FirstOrDefault(u => u.Username == model.Username.ToLower()
                        && u.AuthCode == model.AuthCode);

                    if (user == null)
                    {
                        throw new InvalidOperationException("Invalid username or password");
                    }
                    if (user.SessionKey == null)
                    {
                        user.SessionKey = this.GenerateSessionKey(user.Id);
                        context.SaveChanges();
                    }

                    var loggedModel = new LoggedUserModel()
                    {
                        Name = user.Name,
                        SessionKey = user.SessionKey
                    };

                    var response = this.Request.CreateResponse(HttpStatusCode.Created,
                                        loggedModel);
                    return response;
                }
            }
            catch (Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.BadRequest,
                                         ex.Message);
                return response;
            }
        }
        public HttpResponseMessage PostPlace(NationalPlaceModel place)
        {
            try
            {
                var context = new NationalPlacesContext();
                using(context)
                {
                    if(place.Name==null || place.Name=="")
                    {
                        throw  new ArgumentNullException("Inavalid place name");
                    }

                    if(place.Description==null || place.Description=="")
                    {
                        throw new ArgumentNullException("Invalid description");
                    }

                    var town=context.Towns.FirstOrDefault(t => t.Name == place.Town);
                    if (town==null)
                    {
                        town=context.Towns.Add(new Town()
                                              {
                                                  Name = place.Town,
                                              });
                        context.SaveChanges();
                    }

                    Place newPlace = new Place()
                                         {
                                             Name = place.Name,
                                             Description = place.Description,
                                             Town = town,
                                             PictureUrl = place.PictureUrl,
                                             Latitude=place.Latitude,
                                             Longitude = place.Longitude
                                         };

                    context.Places.Add(newPlace);
                    context.SaveChanges();
                    var response = this.Request.CreateResponse(HttpStatusCode.Created);
                    return response;
                }
            }
            catch(Exception ex)
            {
                var response = this.Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
                return response;
            }
        }
 public HttpResponseMessage GetPlacesByTownId(int townId)
 {
     try
     {
         var context = new NationalPlacesContext();
         var allPlaces = from place in context.Towns.FirstOrDefault(t => t.Id == townId).Places
                         select new NationalPlaceModel()
                                    {
                                        Id = place.Id,
                                        Name=place.Name,
                                        PictureUrl = place.PictureUrl
                                    };
         var response = this.Request.CreateResponse(HttpStatusCode.OK, allPlaces);
         return response;
     }
     catch(Exception ex)
     {
         var response = this.Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
         return response;
     }
 }