using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using AutoMapper;
using Qusion.Cms.Classifications.Core;
using Qusion.Cms.Core;
using Qusion.Cms.Core.Domain;
using Qusion.Cms.Core.Exceptions;
using Qusion.Cms.Core.Security;
using Qusion.Cms.Modules.Blogs.Core;
using Qusion.Cms.Modules.Blogs.Domain;
using Qusion.Cms.Users.Core;
using Qusion.Cms.Users.Domain;
using Qusion.Cms.Web.Http;
using Qusion.WebApp.Areas.Qusion.Filters;
using Qusion.WebApp.Areas.Qusion.Models.Blogs;

namespace Qusion.WebApp.Areas.Qusion.Controllers.Api
{
   [Authorize(Roles = "Administrator,Administrators")]
    public class BlogController : ApiController
    {
       
        private readonly BlogService _blogService;
        private readonly LabelService _labelService;
        private readonly BlogPostService _postService;
        private readonly UserService _userService;

        public BlogController(BlogService blogService, UserService userService, BlogPostService postService,
                              LabelService labelService)
        {
            _blogService = blogService;
            _userService = userService;
            _postService = postService;
            _labelService = labelService;
        }

        [HttpPost]
        [ModelValidationFilter]
        [Authorize(Roles = "Administrator,Administrators,Radnik")]
        public HttpResponseMessage Create(BlogCreateModel newBlog)
        {
            User owner = _userService.Current();
            Blog blog = Mapper.Map<BlogCreateModel, Blog>(newBlog);
            blog.Owner = owner;
            blog.Status = WorkflowStatus.Draft;
            try
            {
                blog.Alias = _blogService.GenerateAlias(string.IsNullOrEmpty(blog.Alias) ? blog.Title : blog.Alias);
            }
            catch (AliasException e)
            {
                var errors = new Dictionary<string, string[]>();
                errors.Add("newBlog.Alias", new[] {"utility.InvalidAlias"});
                return Request.CreateResponse(HttpStatusCode.OK, new {Errors = errors});
            }
            _blogService.Save(blog);
            return Request.CreateResponse(HttpStatusCode.OK, Mapper.Map<Blog, BlogModel>(blog));
        }

        [HttpPost]
        [ModelValidationFilter]
        [Authorize(Roles = "Administrator,Administrators,Radnik")]
        public HttpResponseMessage Edit(BlogEditModel blog)
        {
            Blog newBlog = _blogService.GetById(blog.ID);

            try
            {
                if (newBlog.Alias != blog.Alias)
                {
                    blog.Alias = _blogService.GenerateAlias(blog.Alias);
                }
                Mapper.Map(blog, newBlog);
                _blogService.Save(newBlog);
            }
            catch (AliasException e)
            {
                var errors = new Dictionary<string, string[]>();
                errors.Add("blog.Alias", new[] {"utility.InvalidAlias"});
                return Request.CreateResponse(HttpStatusCode.OK, new {Errors = errors});
            }

            return Request.CreateResponse(HttpStatusCode.OK, Mapper.Map<Blog, BlogModel>(newBlog));
        }

        [HttpGet]
        public BlogModel Get(Guid id)
        {
            Blog blog = _blogService.GetById(id);
            return Mapper.Map<Blog, BlogModel>(blog);
        }

        [HttpGet]
        public PageResult<BlogListModel> Query([FromUri] BlogQueryInput input)
        {
            BlogQuery query = Mapper.Map(input, BlogQuery.Default) ?? BlogQuery.Default;
            IEnumerable<Blog> blogs = _blogService.Search(query);
            IList<BlogListModel> model = Mapper.Map<IList<Blog>, IList<BlogListModel>>(blogs.ToList());

            return new PageResult<BlogListModel>
                       {
                           Items = model,
                           Count = query.Paging.TotalCount
                       };
        }

        [HttpGet]
        public HttpResponseMessage Delete(Guid id)
        {
            Blog blog = _blogService.GetById(id);
            _blogService.Delete(blog);
            return Request.CreateResponse(HttpStatusCode.OK);
        }

        /********************************************************************
         *******                 Posts manipulation                 *********
         *******************************************************************/

        [HttpGet]
        public PageResult<BlogPostListModel> QueryPosts([FromUri] BlogPostQueryInput input)
        {
            BlogPostQuery post = Mapper.Map(input, BlogPostQuery.Default) ?? BlogPostQuery.Default;
            IEnumerable<BlogPost> posts = _postService.Search(post);
            IList<BlogPostListModel> model = Mapper.Map<IList<BlogPost>, IList<BlogPostListModel>>(posts.ToList());

            return new PageResult<BlogPostListModel>
                       {
                           Items = model,
                           Count = post.Paging.TotalCount
                       };
        }

      
        [HttpPost]
        [ModelValidationFilter]
        [Authorize(Roles = "Administrator,Administrators,Radnik")]
        public HttpResponseMessage CreatePost(PostCreateModel post)
        {
            Blog blog = _blogService.GetById(post.BlogID);
            BlogPost newPost = Mapper.Map<PostCreateModel, BlogPost>(post);
            newPost.Blog = blog;
            newPost.Status = WorkflowStatus.Draft;
            newPost.Labels.Clear();
            foreach (string labelId in post.Labels)
            {
                newPost.Labels.Add(_labelService.GetById(new Guid(labelId)));
            }
            try
            {
                _postService.Save(newPost);
            }
            catch (AliasException e)
            {
                var errors = new Dictionary<string, string[]>();
                errors.Add("post.Alias", new[] { "utility.InvalidAlias" });
                return Request.CreateResponse(HttpStatusCode.OK, new { Errors = errors });
            }

            return Request.CreateResponse(HttpStatusCode.OK, Mapper.Map<BlogPost, BlogPostListModel>(newPost));
        }


        [HttpGet]
        public HttpResponseMessage PostForEdit(Guid id)
        {
            BlogPost post = _postService.GetById(id);

            return Request.CreateResponse(HttpStatusCode.OK, Mapper.Map<BlogPost, PostModel>(post));
        }

        [HttpPost]
        [ModelValidationFilter]
        [Authorize(Roles = "Administrator,Administrators,Radnik")]
        public HttpResponseMessage UpdatePost(PostEidtModel post)
        {
            
                BlogPost newPost = _postService.GetById(post.ID);
                
                newPost.Labels.Clear();
                foreach (string labelId in post.Labels)
                    newPost.Labels.Add(_labelService.GetById(new Guid(labelId)));

                try
                {
                    if (newPost.Alias != post.Alias)
                    {
                        post.Alias = _blogService.GenerateAlias(post.Alias);
                    }
                    Mapper.Map(post, newPost);
                    _postService.Save(newPost);
                }
                catch (AliasException e)
                {
                    var errors = new Dictionary<string, string[]>();
                    errors.Add("post.Alias", new[] { "utility.InvalidAlias" });
                    return Request.CreateResponse(HttpStatusCode.OK, new { Errors = errors });
                }
               
                return Request.CreateResponse(HttpStatusCode.OK, Mapper.Map<BlogPost, PostEidtModel>(newPost));
            
        }

        [HttpGet]
        public HttpResponseMessage DeletePost(Guid id)
        {
            BlogPost post = _postService.GetById(id);
            _postService.Delete(post);
            return Request.CreateResponse(HttpStatusCode.OK);
        }
    }
}