using Autofac;
using GreenTree.Nachtragsmanagement.Core;
using GreenTree.Nachtragsmanagement.Core.Authentication;
using GreenTree.Nachtragsmanagement.Services.User;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;

namespace GreenTree.Nachtragsmanagement.Web.Framework.Authorization
{
    public class FunctionAuthorizeAttribute : AuthorizeAttribute
    {
        #region Fields

        private readonly IAuthenticationService _authenticationService;
        private readonly IUserHelper _userHelper;
        private readonly IUserService _userService;
        private readonly string[] _allowedFunctions;
        private readonly bool _showNotAuthorized;

        #endregion

        /// <summary>
        /// Initializes a new instance of the FunctionAuthorizeAttribute class
        /// </summary>
        /// <param name="showNotAuthorized">Determines if a NotAuthorized message or a login redirection is made.</param>
        /// <param name="functions">The functions needed.</param>
        public FunctionAuthorizeAttribute(bool showNotAuthorized, params string[] functions)
        {
            _showNotAuthorized = showNotAuthorized;
            _allowedFunctions = functions;

            _authenticationService = Singleton<IContainer>.Instance.Resolve<IAuthenticationService>();
            _userHelper = Singleton<IContainer>.Instance.Resolve<IUserHelper>();
            _userService = Singleton<IContainer>.Instance.Resolve<IUserService>();
        }

        /// <summary>
        /// Core authorization
        /// </summary>
        /// <param name="httpContext">Current HttpContext.</param>
        /// <returns>Valid access.</returns>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var cookieUser = _userHelper.FromCookiesOrSession();

            if (cookieUser == null)
                return false;

            if (!_allowedFunctions.Any())
                return true;

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

            var role = (cookieUser != null && cookieUser.CurrentRole != null)
                ? _userService.GetRoleById(cookieUser.CurrentRole.Id)
                : null;

            if (role == null)
                dbUser.CurrentRole = dbUser.Roles
                    .First(r1 => r1.Level == dbUser.Roles.Max(r2 => r2.Level));
            else
                dbUser.CurrentRole = role;

            _userHelper.ToCookiesAndSession(dbUser, DateTime.Now.AddHours(8), true);

            foreach (var function in dbUser.CurrentRole.Functions)
            {
                var allowed = _allowedFunctions.Contains(function.Name);

                if (allowed)
                    return true;
            }

            return false;
        }

        /// <summary>
        /// Handle not authorized access
        /// </summary>
        /// <param name="filterContext">Current filterContext.</param>
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (!_showNotAuthorized)
                filterContext.Result = new RedirectResult("~/login");
            else
                filterContext.Result = new RedirectResult("~/global/notauthorized");
        }
    }
}
