using GreenTree.Nachtragsmanagement.Core;
using GreenTree.Nachtragsmanagement.Core.Authentication;
using GreenTree.Nachtragsmanagement.Services.Appendix;
using GreenTree.Nachtragsmanagement.Services.Configuration;
using GreenTree.Nachtragsmanagement.Services.Deviation;
using GreenTree.Nachtragsmanagement.Services.Logging;
using GreenTree.Nachtragsmanagement.Services.Site;
using GreenTree.Nachtragsmanagement.Services.User;
using GreenTree.Nachtragsmanagement.Web.Models.Global;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace GreenTree.Nachtragsmanagement.Web.Controllers
{
    public class GlobalController : Controller
    {
        private readonly IUserHelper _userHelper;
        private readonly IUserService _userService;
        private readonly IAppendixService _appendixService;
        private readonly IDeviationService _deviationService;
        private readonly ISiteService _siteService;
        private readonly IConfigurationService _configurationService;
        private readonly ILogger _logger;

        public GlobalController(
            IUserHelper userHelper,
            IUserService userService,
            IAppendixService appendixService,
            IDeviationService deviationService,
            ISiteService siteService,
            IConfigurationService configurationService,
            ILogger logger)
        {
            _userHelper = userHelper;
            _userService = userService;
            _appendixService = appendixService;
            _deviationService = deviationService;
            _siteService = siteService;
            _configurationService = configurationService;
            _logger = logger;
        }

        /// <summary>
        /// Represents the global Footer
        /// </summary>
        public ActionResult Footer()
        {
            var cookieUser = _userHelper.FromCookiesOrSession();

            if (cookieUser == null)
                return View("~/Views/Shared/_Footer.cshtml", null);

            var dbUser = _userService.GetUserById(cookieUser.Id);

            if (dbUser == null)
                return View("~/Views/Shared/_Footer.cshtml", null);

            var footerModel = new FooterModel
            {
                CustomNumber = dbUser.CustomNumber,
                Forename = dbUser.Forename,
                Lastname = dbUser.Lastname,
                RoleDescription = dbUser.CurrentRole.Description
            };

            ViewData["Roles"] =
                dbUser.Roles
                    .Select(r => new
                    {
                        r.Id,
                        r.Description
                    });

            return View("~/Views/Shared/_Footer.cshtml", footerModel);
        }

        /// <summary>
        /// Sets the current role of the logged in user and redirects to the home page
        /// </summary>
        /// <param name="roleId">The id of the new role.</param>
        public ActionResult SetRole(int roleId = -1)
        {
            try
            {
                if (roleId == -1)
                    return RedirectToAction("Index", "Home");

                var user = _userHelper.FromCookiesOrSession();
                var role = _userService.GetRoleById(roleId);

                user.CurrentRole = role;

                _userHelper.ToCookiesAndSession(user);
            }
            catch (Exception ex)
            {
                _logger.Error("Fehler bei Wechsel einer Rolle.", ex, _userHelper.FromCookiesOrSession());
            }

            return RedirectToAction("Index", "Home");
        }

        /// <summary>
        /// Shows an unauthorized message
        /// </summary>
        public ActionResult NotAuthorized()
        {
            return View("~/Views/Global/NotAuthorized.cshtml");
        }

        /// <summary>
        /// Deletes the specified cookies and session variables from request
        /// </summary>
        /// <param name="cookies">Cookie names.</param>
        /// <param name="sessionVariables">Session variable names.</param>
        /// <param name="userConfigItemNames">Names of userConfigItems.</param>
        [HttpPost]
        public ActionResult DeleteCookiesSessionVariablesAndUserConfigs(string[] cookies, string[] sessionVariables, 
            string[] userConfigItemNames)
        {
            if (cookies != null && cookies.Length > 0)
            {
                foreach (var cookieName in cookies)
                {
                    var cookie = Request.Cookies[cookieName];

                    if (cookie != null)
                    {
                        cookie.Expires = DateTime.Now.AddDays(-1);

                        Request.Cookies.Set(cookie);
                        Response.Cookies.Set(cookie);
                    }
                }
            }

            if (sessionVariables != null && sessionVariables.Length > 0)
            {
                foreach (var sessionVariable in sessionVariables)
                {
                    if (Session[sessionVariable] != null)
                        Session.Remove(sessionVariable);
                }
            }

            if (userConfigItemNames != null && userConfigItemNames.Length > 0)
            {
                var user = CommonHelper.UserContext().CurrentUser;

                foreach (var userConfigItemName in userConfigItemNames)
                {
                    var userConfigItem = _configurationService.GetUserConfigItemByNameAndUserId(userConfigItemName, user.Id);

                    if (userConfigItem != null)
                        _configurationService.DeleteUserConfigItem(userConfigItem);
                }
            }

            return new JsonResult
            {
                Data = "success"
            };
        }

        #region Comments

        /// <summary>
        /// Gets a full comment of a given entity
        /// </summary>
        /// <param name="entityType">The entity type.</param>
        /// <param name="id">The entity id.</param>
        public ActionResult GetEntityComment(string entityType, int id)
        {
            var result = new JsonResult
            {
                JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                Data = String.Empty
            };

            if (String.IsNullOrEmpty(entityType))
                return result;

            switch (entityType)
            {
                case "appendix":
                    var appendix = _appendixService.GetAppendixById(id);

                    result.Data = appendix.Comment;
                    break;
                case "deviation":
                    var deviation = _deviationService.GetDeviationById(id);

                    result.Data = deviation.Comment;
                    break;
                case "site":
                    var site = _siteService.GetSiteById(id);

                    result.Data = site.Comment;
                    break;
                default:
                    return result;
            }

            return result;
        }

        /// <summary>
        /// Gets a full comment of a given entity and provides an edit form
        /// </summary>
        /// <param name="entityType">The entity type.</param>
        /// <param name="id">The entity id.</param>
        public ActionResult EditEntityComment(string entityType, int id)
        {
            var editCommentModel = new EditEntityCommentModel
            {
                EntityType = entityType,
                EntityId = id
            };

            switch (entityType)
            {
                case "appendix":
                    var appendix = _appendixService.GetAppendixById(id);

                    editCommentModel.Comment = appendix.Comment;
                    break;
                case "deviation":
                    var deviation = _deviationService.GetDeviationById(id);

                    editCommentModel.Comment = deviation.Comment;
                    break;
                case "site":
                    var site = _siteService.GetSiteById(id);

                    editCommentModel.Comment = site.Comment;
                    break;
                default:
                    return new EmptyResult();
            }

            return PartialView("~/Views/Shared/_EditCommentPartial.cshtml", editCommentModel);
        }

        /// <summary>
        /// Sets a comment for a given entity
        /// </summary>
        /// <param name="entityType">The entity type.</param>
        /// <param name="id">The entity id.</param>
        [HttpPost, ValidateInput(false)]
        public ActionResult EditEntityComment(EditEntityCommentModel model)
        {
            if (model == null)
                return new EmptyResult();

            switch (model.EntityType)
            {
                case "appendix":
                    var appendix = _appendixService.GetAppendixById(model.EntityId);

                    appendix.Comment = model.Comment;

                    _appendixService.UpdateAppendix(appendix);

                    _logger.Entity(appendix, Core.Domain.Logging.LogEntityActivity.Update, _userHelper.FromCookiesOrSession());
                    break;
                case "deviation":
                    var deviation = _deviationService.GetDeviationById(model.EntityId);

                    deviation.Comment = model.Comment;

                    _deviationService.UpdateDeviation(deviation);

                    _logger.Entity(deviation, Core.Domain.Logging.LogEntityActivity.Update, _userHelper.FromCookiesOrSession());
                    break;
                case "site":
                    var site = _siteService.GetSiteById(model.EntityId);

                    site.Comment = model.Comment;

                    _siteService.UpdateSite(site);

                    _logger.Entity(site, Core.Domain.Logging.LogEntityActivity.Update, _userHelper.FromCookiesOrSession());
                    break;
                default:
                    return new EmptyResult();
            }

            return new JsonResult
            {
                Data = "success"
            };
        }

        #endregion
    }
}