using GreenTree.Nachtragsmanagement.Core.Domain.User;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace GreenTree.Nachtragsmanagement.Core.Authentication
{
    public class UserHelper : IUserHelper
    {
        /// <summary>
        /// Default serializer settings
        /// </summary>
        private static JsonSerializerSettings _jsonSerializerSettigs = new JsonSerializerSettings
        {
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore
        };

        /// <summary>
        /// Evaluates the current user from request cookies
        /// </summary>
        public User FromCookiesOrSession()
        {
            return FromCookiesOrSession(8);
        }

        /// <summary>
        /// Evaluates the current user from request cookies
        /// </summary>
        /// <param name="expirationHoursIncrease">The hours the authCookie will be increased if it exists.</param>
        public User FromCookiesOrSession(int expirationHoursIncrease)
        {
            if (HttpContext.Current == null || HttpContext.Current.Session == null) return null;

            User user = null;

            if (HttpContext.Current.Session["auth"] != null)
                user = HttpContext.Current.Session["auth"] as User;

            if (user != null)
                return user;

            var authCookie = HttpContext.Current.Request.Cookies["auth"];

            if (authCookie == null)
                return null;

            user = JsonConvert.DeserializeObject<User>(StaticHelper.DecompressString(authCookie.Value));

            if (user != null)
            {
                authCookie.Expires = DateTime.Now.AddHours(expirationHoursIncrease);

                HttpContext.Current.Response.Cookies.Set(authCookie);
            }

            return user;
        }

        /// <summary>
        /// Writes the current user to response cookies
        /// </summary>
        /// <param name="user">The current authenticated user.</param>
        public void ToCookiesAndSession(User user)
        {
            ToCookiesAndSession(user, false);
        }

        /// <summary>
        /// Writes the current user to response cookies
        /// </summary>
        /// <param name="user">The current authenticated user.</param>
        /// <param name="setRequestCookie">Set also the request cookie for further authorization.</param>
        public void ToCookiesAndSession(User user, bool setRequestCookie)
        {
            if (HttpContext.Current == null || HttpContext.Current.Session == null) return;

            var authCookie = HttpContext.Current.Request.Cookies["auth"];

            var userJson = JsonConvert.SerializeObject(user, _jsonSerializerSettigs);

            authCookie = new HttpCookie("auth", StaticHelper.CompressString(userJson))
            {
                Expires = authCookie.Expires
            };

            HttpContext.Current.Response.Cookies.Set(authCookie);

            if (setRequestCookie)
                HttpContext.Current.Request.Cookies.Set(authCookie);

            HttpContext.Current.Session["auth"] = user;
        }

        /// <summary>
        /// Writes the current user to response cookies
        /// </summary>
        /// <param name="user">The current authenticated user.</param>
        /// <param name="expirationDate">The cookie expiration date.</param>
        public void ToCookiesAndSession(User user, DateTime expirationDate)
        {
            ToCookiesAndSession(user, expirationDate, false);
        }

        /// <summary>
        /// Writes the current user to response cookies
        /// </summary>
        /// <param name="user">The current authenticated user.</param>
        /// <param name="expirationDate">The cookie expiration date.</param>
        /// <param name="setRequestCookie">Set also the request cookie for further authorization.</param>
        public void ToCookiesAndSession(User user, DateTime expirationDate, bool setRequestCookie)
        {
            if (HttpContext.Current == null || HttpContext.Current.Session == null) return;

            var authCookie = HttpContext.Current.Request.Cookies["auth"];

            var userJson = JsonConvert.SerializeObject(user, _jsonSerializerSettigs);

            authCookie = new HttpCookie("auth", StaticHelper.CompressString(userJson))
            {
                Expires = expirationDate
            };

            HttpContext.Current.Response.Cookies.Set(authCookie);

            if (setRequestCookie)
                HttpContext.Current.Request.Cookies.Set(authCookie);

            HttpContext.Current.Session["auth"] = user;
        }

        /// <summary>
        /// Clears the authentication cookie
        /// </summary>
        public void ClearCookieAndSession()
        {
            if (HttpContext.Current == null || HttpContext.Current.Session == null) return;

            var authCookie = HttpContext.Current.Request.Cookies["auth"];

            if (authCookie == null) return;

            authCookie.Expires = DateTime.Now.AddHours(-1);

            HttpContext.Current.Response.Cookies.Set(authCookie);
            HttpContext.Current.Session.Remove("auth");
        }
    }
}