using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using ServiceStack.Common.Web;
using ServiceStack.ServiceHost;
using System;
using System.Collections.Generic;
namespace MediaBrowser.Api
{
    /// 
    /// Class BaseApiService
    /// 
    [RequestFilter]
    public class BaseApiService : IHasResultFactory, IRestfulService
    {
        /// 
        /// Gets or sets the logger.
        /// 
        /// The logger.
        public ILogger Logger { get; set; }
        /// 
        /// Gets or sets the HTTP result factory.
        /// 
        /// The HTTP result factory.
        public IHttpResultFactory ResultFactory { get; set; }
        /// 
        /// Gets or sets the request context.
        /// 
        /// The request context.
        public IRequestContext RequestContext { get; set; }
        
        /// 
        /// To the optimized result.
        /// 
        /// 
        /// The result.
        /// System.Object.
        protected object ToOptimizedResult(T result)
            where T : class
        {
            return ResultFactory.GetOptimizedResult(RequestContext, result);
        }
        /// 
        /// To the optimized result using cache.
        /// 
        /// 
        /// The cache key.
        /// The last date modified.
        /// Duration of the cache.
        /// The factory fn.
        /// System.Object.
        /// cacheKey
        protected object ToOptimizedResultUsingCache(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func factoryFn)
               where T : class
        {
            return ResultFactory.GetOptimizedResultUsingCache(RequestContext, cacheKey, lastDateModified, cacheDuration, factoryFn);
        }
        /// 
        /// To the cached result.
        /// 
        /// 
        /// The cache key.
        /// The last date modified.
        /// Duration of the cache.
        /// The factory fn.
        /// Type of the content.
        /// System.Object.
        /// cacheKey
        protected object ToCachedResult(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func factoryFn, string contentType)
          where T : class
        {
            return ResultFactory.GetCachedResult(RequestContext, cacheKey, lastDateModified, cacheDuration, factoryFn, contentType);
        }
        /// 
        /// To the static file result.
        /// 
        /// The path.
        /// System.Object.
        protected object ToStaticFileResult(string path)
        {
            return ResultFactory.GetStaticFileResult(RequestContext, path);
        }
    }
    /// 
    /// Class RequestFilterAttribute
    /// 
    public class RequestFilterAttribute : Attribute, IHasRequestFilter
    {
        //This property will be resolved by the IoC container
        /// 
        /// Gets or sets the user manager.
        /// 
        /// The user manager.
        public IUserManager UserManager { get; set; }
        /// 
        /// Gets or sets the logger.
        /// 
        /// The logger.
        public ILogger Logger { get; set; }
        
        /// 
        /// The request filter is executed before the service.
        /// 
        /// The http request wrapper
        /// The http response wrapper
        /// The request DTO
        public void RequestFilter(IHttpRequest request, IHttpResponse response, object requestDto)
        {
            //This code is executed before the service
            var auth = GetAuthorization(request);
            if (auth != null && auth.ContainsKey("UserId"))
            {
                var userId = auth["UserId"];
                if (!string.IsNullOrEmpty(userId))
                {
                    var user = UserManager.GetUserById(new Guid(userId));
                    UserManager.LogUserActivity(user, auth["Client"], auth["DeviceId"], auth["Device"] ?? string.Empty);
                }
            }
        }
        /// 
        /// Gets the auth.
        /// 
        /// The HTTP req.
        /// Dictionary{System.StringSystem.String}.
        public static Dictionary GetAuthorization(IHttpRequest httpReq)
        {
            var auth = httpReq.Headers[HttpHeaders.Authorization];
            return GetAuthorization(auth);
        }
        /// 
        /// Gets the authorization.
        /// 
        /// The HTTP req.
        /// Dictionary{System.StringSystem.String}.
        public static Dictionary GetAuthorization(IRequestContext httpReq)
        {
            var auth = httpReq.GetHeader("Authorization");
            return GetAuthorization(auth);
        }
        
        /// 
        /// Gets the authorization.
        /// 
        /// The authorization header.
        /// Dictionary{System.StringSystem.String}.
        private static Dictionary GetAuthorization(string authorizationHeader)
        {
            if (authorizationHeader == null) return null;
            var parts = authorizationHeader.Split(' ');
            // There should be at least to parts
            if (parts.Length < 2) return null;
            // It has to be a digest request
            if (!string.Equals(parts[0], "MediaBrowser", StringComparison.OrdinalIgnoreCase))
            {
                return null;
            }
            // Remove uptil the first space
            authorizationHeader = authorizationHeader.Substring(authorizationHeader.IndexOf(' '));
            parts = authorizationHeader.Split(',');
            var result = new Dictionary(StringComparer.OrdinalIgnoreCase);
            foreach (var item in parts)
            {
                var param = item.Trim().Split(new[] { '=' }, 2);
                result.Add(param[0], param[1].Trim(new[] { '"' }));
            }
            return result;
        }
        /// 
        /// A new shallow copy of this filter is used on every request.
        /// 
        /// IHasRequestFilter.
        public IHasRequestFilter Copy()
        {
            return this;
        }
        /// 
        /// Order in which Request Filters are executed.
        /// <0 Executed before global request filters
        /// >0 Executed after global request filters
        /// 
        /// The priority.
        public int Priority
        {
            get { return 0; }
        }
    }
}