public HttpResponseMessage AddReview(PropertyReview review)
 {
     try
     {
         PropertyReview resReview = _appointmentManager.AddOrUpdatePropertyReview(review);
         return Request.CreateResponse(HttpStatusCode.OK, resReview);
     }
     catch (ParamMissingException e){
         return Request.CreateResponse(HttpStatusCode.NotAcceptable, new ErrorResponse{ Message = e.Message });
     } catch (AlreadyExistsException e){
         return Request.CreateResponse(HttpStatusCode.Conflict, new ErrorResponse{ Message = e.Message });
     }catch (InvalidValueException e){
         return Request.CreateResponse(HttpStatusCode.NotAcceptable, new ErrorResponse{ Message = e.Message });
     }catch (UserNotFoundException e){
         return Request.CreateResponse(HttpStatusCode.NotFound, new ErrorResponse{ Message = e.Message });
     }catch (Exception e){
         return Request.CreateResponse(HttpStatusCode.InternalServerError, new ErrorResponse { Message = "Oops, server encountered an issue... " + e.Message });
     }
 }
        public PropertyReview AddOrUpdatePropertyReview(PropertyReview argReview)
        {
            if (argReview == null)
                throw new ParamMissingException("PropertyReview must be passed.");

            if (string.IsNullOrWhiteSpace(argReview.UserId))
                throw new ParamMissingException("User Id cannot be empty.");
            if (argReview.ConciergeRating == null)
                throw new ParamMissingException("Concierge rating cannot be empty.");
            if (argReview.PropertyRating == null)
                throw new ParamMissingException("Property rating cannot be empty.");

            if (string.IsNullOrWhiteSpace(argReview.Comment))
                argReview.Comment = null;
            else
                argReview.Comment = argReview.Comment.Trim();

            Property property = Repository.Single<Property>(
                x => x.ListingKey == argReview.ListingKey);
            if (property == null)
                throw new InvalidValueException("The property with provided Id was not found.");

            Appointment appointment = Repository.Single<Appointment>(x => x.ListingKey == argReview.ListingKey
                                                && x.Deleted != true && x.UserId.Equals(argReview.UserId)
                                                && x.AppointmentId == argReview.AppointmentId
                                                && x.Status.Equals("Shown"), "PropertyReview");

            if (appointment == null)
                throw new InvalidValueException("You have not viewed this property yet.");

            PropertyReview previousReview = appointment.PropertyReview;
                                //Repository.Single<PropertyReview>(x => x.UserId.Equals(argReview.UserId) &&
                                //x.ListingKey == argReview.ListingKey && x.AppointmentId == argReview.AppointmentId);
            if (previousReview != null)
            {
                //if (previousReview.PropertyReviewId != argReview.PropertyReviewId)
                //    throw new AlreadyExistsException("You cannot update your review cause your supplied data does not match.");
                //else
                if (previousReview.ListingKey != argReview.ListingKey)
                    throw new InvalidValueException("You cannot change the property in review.");
                else if (previousReview.UserId.Equals(argReview.UserId) == false)
                    throw new InvalidValueException("You cannot change the user in review.");

                property.PropertyRating = ((property.PropertyRating * property.ReviewCount)
                                                    - previousReview.PropertyRating.Value
                                                    + argReview.PropertyRating.Value) / property.ReviewCount;

                property.ConciergeRating = ((property.ConciergeRating * property.ReviewCount)
                                                    - previousReview.ConciergeRating.Value
                                                    + argReview.ConciergeRating.Value) / property.ReviewCount;

                previousReview.PropertyRating = argReview.PropertyRating;
                previousReview.Comment = argReview.Comment;
                previousReview.ConciergeRating = argReview.ConciergeRating;
                previousReview.Created = DateTime.UtcNow;
                Repository.Save();
                return previousReview;
            }
            else
            {
                // Update property stats so have a summary with property.
                property.PropertyRating = ((property.PropertyRating * property.ReviewCount)
                                                    + argReview.PropertyRating.Value) / (property.ReviewCount + 1);
                property.ConciergeRating = ((property.ConciergeRating * property.ReviewCount)
                                                    + argReview.ConciergeRating.Value) / (property.ReviewCount + 1);

                property.ReviewCount = property.ReviewCount + 1;
                // Save changes.
                argReview.Created = DateTime.UtcNow;
                argReview.PropertyReviewId = 0;
                PropertyReview newReview = new PropertyReview()
                {
                    Comment = argReview.Comment,
                    AppointmentId = appointment.AppointmentId,
                    ConciergeRating = argReview.ConciergeRating,
                    Created = DateTime.UtcNow,
                    ListingKey = appointment.ListingKey.Value,
                    PropertyRating = argReview.PropertyRating,
                    UserId = argReview.UserId,
                };
                Repository.Add<PropertyReview>(newReview);
                appointment.PropertyReview = newReview;
                Repository.Save();
                //appointment.PropertyReviewId = newReview.PropertyReviewId;
                //Repository.Save();
                return newReview;
            }
        }