public HttpResponseMessage GetPage(int page, int count, [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey)
        {
            var responceMsg = this.PerformOperationAndHandleExceptions(() =>
            {
                var context = new ForumDbContext();
                using (context)
                {
                    var user = context.Users.FirstOrDefault(usr =>
            usr.SessionKey == sessionKey);

                    if (user == null)
                    {
                        throw new InvalidOperationException("Invalid username and password.");
                    }

                    var threadEntities = context.Threads.OrderBy(x => x.DateCreated).Skip(page * count).Take(count);
                    var models = (from threadEntity in threadEntities
                                  select new ThreadModel()
                                  {
                                      Id = threadEntity.Id,
                                      Title = threadEntity.Title,
                                      DateCreated = threadEntity.DateCreated,
                                      Content = threadEntity.Content,
                                      CreatedBy = threadEntity.User.Nickname,
                                      Posts = (from postEntity in threadEntity.Posts
                                               select new PostModel()
                                               {
                                                   Content = postEntity.PostContent,
                                                   PostDate = postEntity.PostDate,
                                                   PostedBy = postEntity.User.Nickname
                                               }),
                                      Categories = (from categoryEntity in threadEntity.Categories
                                                    select categoryEntity.CategoryName)
                                  });
                    var ordered = models.OrderByDescending(thr => thr.DateCreated).ToList();

                    var responce = this.Request.CreateResponse(HttpStatusCode.OK, ordered);

                    return responce;

                }
            });

            return responceMsg;
        }
        public HttpResponseMessage PostLoginUser(UserModel model)
        {
            var responceMsg = this.PerformOperationAndHandleExceptions(() =>
            {
                var context = new ForumDbContext();
                using (context)
                {
                    this.ValidateUsername(model.Username);
                    this.ValidateAuthCode(model.AuthCode);

                    var usernameToLower = model.Username.ToLower();
                    var authCode = model.AuthCode;

                    var user = context.Users.FirstOrDefault(usr =>
            usr.Username == usernameToLower && usr.AuthCode == authCode);

                    if (user == null)
                    {
                        throw new InvalidOperationException("Ivalid username or password");
                    }

                    if (user.SessionKey == null)
                    {
                        user.SessionKey = this.GenerateSessionKey(user.Id);
                        context.SaveChanges();
                    }

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

                    var responce = this.Request.CreateResponse(HttpStatusCode.OK, loggedModel);

                    return responce;

                }
            });

            return responceMsg;
        }
        // POST api/posts
        public HttpResponseMessage Post(PostModel value, [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey)
        {
            var responceMsg = this.PerformOperationAndHandleExceptions(() =>
            {
                var context = new ForumDbContext();
                using (context)
                {
                    var user = context.Users.FirstOrDefault(usr => usr.SessionKey == sessionKey
                        && usr.Nickname == value.PostedBy);

                    if (user == null)
                    {
                        throw new InvalidOperationException("Invalid username and password.");
                    }

                    Post newPost = new Post()
                    {
                        PostDate = DateTime.Now,
                        PostContent = value.Content,
                        Thread = context.Threads.FirstOrDefault(x => x.Id == value.ThreadId),
                        User = user
                    };

                    context.Posts.Add(newPost);
                    context.SaveChanges();

                    //newPost.User = null;

                    var responce = this.Request.CreateResponse(HttpStatusCode.Created);

                    return responce;

                }
            });

            return responceMsg;
        }
        public HttpResponseMessage PutLogoutUser(LoggedUserModel model)
        {
            var responceMsg = this.PerformOperationAndHandleExceptions(() =>
            {
                var context = new ForumDbContext();
                using (context)
                {
                    var sessionKey = model.SessionKey;

                    var user = context.Users.FirstOrDefault(usr =>
            usr.SessionKey == sessionKey);

                    if (user == null)
                    {
                        throw new InvalidOperationException("Something went terribly wrong");
                    }

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

                    var responce = this.Request.CreateResponse(HttpStatusCode.NoContent);

                    return responce;

                }
            });

            return responceMsg;
        }
        public HttpResponseMessage PostRegisterUser(UserModel model)
        {
            var responceMsg = this.PerformOperationAndHandleExceptions(() =>
                {

                    var context = new ForumDbContext();
                    using (context)
                    {
                        this.ValidateUsername(model.Username);
                        this.ValidateNickname(model.Nickname);
                        this.ValidateAuthCode(model.AuthCode);

                        var usernameToLower = model.Username.ToLower();
                        var nicknameToLower = model.Nickname.ToLower();

                        var user = context.Users.FirstOrDefault(usr =>
            usr.Username == usernameToLower || usr.Nickname.ToLower() == nicknameToLower);

                        if (user != null)
                        {
                            throw new InvalidOperationException("User Exists");
                        }

                        user = new User()
                        {
                            Username = usernameToLower,
                            Nickname = model.Nickname,
                            AuthCode = model.AuthCode
                        };

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

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

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

                        var responce = this.Request.CreateResponse(HttpStatusCode.Created, loggedModel);

                        return responce;

                    }
                });

            return responceMsg;
        }
        public IEnumerable<Category> SerializeCategories(ForumDbContext context, IEnumerable<string> categories)
        {
            if (categories == null)
            {
                yield return null;
            }
            foreach (var category in categories)
            {
                var foundCat = (from c in context.Categories
                                where c.CategoryName == category
                                select c).FirstOrDefault();

                if (foundCat == null)
                {
                    continue;
                }
                yield return new Category()
                    {
                        CategoryName = foundCat.CategoryName
                    };
            }
        }
        public HttpResponseMessage Posts(int threadId, [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey)
        {
            var responceMsg = this.PerformOperationAndHandleExceptions(() =>
            {
                var context = new ForumDbContext();
                using (context)
                {
                    var user = context.Users.FirstOrDefault(usr =>
            usr.SessionKey == sessionKey);

                    if (user == null)
                    {
                        throw new InvalidOperationException("Invalid username and password.");
                    }

                    var threadEntity = context.Threads.FirstOrDefault(x => x.Id == threadId);

                    var posts = (from postEntity in threadEntity.Posts
                                 select new PostModel()
                                 {
                                     Content = postEntity.PostContent,
                                     PostDate = postEntity.PostDate,
                                     PostedBy = postEntity.User.Nickname
                                 }).ToList();

                    var responce = this.Request.CreateResponse(HttpStatusCode.OK, posts);

                    return responce;

                }
            });

            return responceMsg;
        }
        // POST api/threads
        public HttpResponseMessage Post(ThreadModel value, [ValueProvider(typeof(HeaderValueProviderFactory<string>))] string sessionKey)
        {
            var responceMsg = this.PerformOperationAndHandleExceptions(() =>
            {
                var context = new ForumDbContext();
                using (context)
                {
                    var user = context.Users.FirstOrDefault(usr =>
            usr.Nickname == value.CreatedBy && usr.SessionKey == sessionKey);

                    if (user == null)
                    {
                        throw new InvalidOperationException("Invalid username and password.");
                    }

                    Thread newThread = new Thread()
                    {
                        Categories = new HashSet<Category>(SerializeCategories(context, value.Categories)),
                        DateCreated = DateTime.Now,
                        Content = value.Content,
                        Posts = null,
                        Title = value.Title,
                        User = user
                    };

                    context.Threads.Add(newThread);
                    context.SaveChanges();

                    newThread.User = null;

                    var responce = this.Request.CreateResponse(HttpStatusCode.Created, newThread);

                    return responce;

                }
            });

            return responceMsg;
        }