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.Core.Exceptions;
using Qusion.Cms.Site;
using Qusion.Cms.Site.Core;
using Qusion.Cms.Web.Http;
using Qusion.WebApp.Areas.Qusion.Filters;
using Qusion.WebApp.Areas.Qusion.Models.Pages;
using Qusion.Framework.Configuration;
using Qusion.WebApp.Areas.Qusion.Helpers;

namespace Qusion.WebApp.Areas.Qusion.Controllers.Api
{
    [Authorize]
    public class PageController : ApiController
    {
        private readonly PageService _pageService;
        private readonly SiteService _siteService;

        public PageController(PageService pageService, SiteService siteService)
        {
            _pageService = pageService;
            _siteService = siteService;
        }

        /// <summary>
        ///   Gets list of all pages.
        /// </summary>
        /// <returns> </returns>
        [HttpGet]
        public PageResult<PageListModel> Query([FromUri] PageQueryInput input)
        {
            PageQuery query = Mapper.Map(input, PageQuery.Default) ?? PageQuery.Default;
                 IEnumerable<Page> pages = _pageService.Search(query);
                 var a = pages.ToList().Where(x => x.Title != null);
                 IList<PageListModel> model = Mapper.Map<IList<Page>, IList<PageListModel>>(a.ToList());

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

        /// <summary>
        /// Gets list of top pages.
        /// </summary>
        /// <returns> </returns>
        [HttpGet]
        public PageResult<PageListModel> Top(Guid? parentID = null)
        {
           IList<Page> pages;
                 if (parentID.HasValue)
                 {
                     Page page = _pageService.GetById(parentID.Value);
                     pages = page != null ? page.Children : new List<Page>();
                 }
                 else
                 {
                     IEnumerable<Page> tree = _pageService.GetTopPages();
                     pages = _pageService.SortByOrdinal(tree).ToList();
                 }
                 var a = pages.ToList().Where(x => x.Title != null);
                 IList<PageListModel> model = Mapper.Map<IList<Page>, IList<PageListModel>>(a.ToList());

                 return new PageResult<PageListModel>
                 {
                     Items = model,
                     Count = pages.Count
                 };
             
             
        }

        /// <summary>
        ///   Get page for edit
        /// </summary>
        /// <param name="id"> </param>
        /// <returns> </returns>
        [HttpGet]
        public HttpResponseMessage GetForEdit(Guid id)
        {
          Page page = _pageService.GetById(id);
           PageEditInput model = Mapper.Map<Page, PageEditInput>(page);
         if (page.InternalRedirect != null)
                     model.InternalRedirectID = page.InternalRedirect.GuidID;

                 return Request.CreateResponse(HttpStatusCode.OK, model);
             
        }

        /// <summary>
        ///   Create new page.
        /// </summary>
        /// <returns> </returns>
        [HttpPost]
        [ModelValidationFilter]
        [Authorize(Roles = "Administrator,Administrators,Radnik")]
        public HttpResponseMessage Create(PageCreateInput page)
        {
            Page newPage = Mapper.Map<PageCreateInput, Page>(page);

            if (page.InternalRedirectID.HasValue)
                newPage.InternalRedirect = _pageService.GetById(page.InternalRedirectID);

            if (page.ParentID.HasValue)
                newPage.Parent = _pageService.GetById(page.ParentID.Value);

            try
            {
                newPage.Alias = _pageService.GenerateAlias(String.IsNullOrEmpty(page.Alias) ? page.Title : page.Alias);
            }
            catch (AliasException e)
            {
                var errors = new Dictionary<string, string[]>();
                errors.Add("page.Alias", new string[] {"utility.InvalidAlias"});
                return Request.CreateResponse(HttpStatusCode.OK, new {Errors = errors});

            }

            newPage.SiteInfo = _siteService.GetCurrent();

            _pageService.Save(newPage);
            return Request.CreateResponse(HttpStatusCode.OK);
        }

        /// <summary>
        ///   Update existing page.
        /// </summary>
        /// <param name="input"> PageEditInput model </param>
        /// <returns> </returns>
        [ModelValidationFilter]
        [Authorize(Roles = "Administrator,Administrators,Radnik")]
        public HttpResponseMessage Edit(PageEditInput page)
        {

            Page domainPage = _pageService.GetById(page.ID);

            if (domainPage.Alias != page.Alias)
            {
                try
                {
                    page.Alias = _pageService.GenerateAlias(page.Alias);
                }
                catch (AliasException e)
                {
                    var errors = new Dictionary<string, string[]>();
                    errors.Add("page.Alias", new string[] {"utility.InvalidAlias"});
                    return Request.CreateResponse(HttpStatusCode.OK, new {Errors = errors});

                }
            }
            Mapper.Map(page, domainPage);

            if (page.InternalRedirectID.HasValue)
                domainPage.InternalRedirect = _pageService.GetById(page.InternalRedirectID);

            _pageService.Save(domainPage);

            return Request.CreateResponse(HttpStatusCode.OK);
        }

        [HttpPost]
        public HttpResponseMessage Delete(Guid id)
        {
            Page page = _pageService.GetById(id);

            if (page != null && page.Children.Count == 0)
            {
                _pageService.Delete(page);
                return Request.CreateResponse(HttpStatusCode.OK);
            }

            return Request.CreateResponse(HttpStatusCode.OK,
                                          new {error = true, message = "Ne možete obrisati stranicu koja ima potomke."});
        }

        [HttpPost]
        public HttpResponseMessage Root(Guid id)
        {
            Page page = _pageService.GetById(id);

            if (page == null)
                return Request.CreateResponse(HttpStatusCode.NotFound);

            _siteService.SetRoot(page);

            PageListModel model = Mapper.Map<Page, PageListModel>(page);
            return Request.CreateResponse(HttpStatusCode.OK, model);
        }

        [HttpPost]
        public HttpResponseMessage Reorder(PageReorderListModel model)
        {
            ReorderPage(model.Pages, null);
            return Request.CreateResponse(HttpStatusCode.OK);
        }

        private void ReorderPage(IEnumerable<PageReorderModel> pages, Page parent)
        {
            int index = 1;
            foreach (PageReorderModel page in pages)
            {
                Page current = _pageService.GetById(new Guid(page.ID));
                current.Parent = null;
                current.Ordinal = index++;
                _pageService.Save(current);
                if (parent != null)
                {
                    current.Parent = parent;
                    _pageService.Save(parent);
                }
                if (page.Children.Count > 0)
                {
                    ReorderPage(page.Children, current);
                }
            }
        }

    }
}