using System;
using System.IO; 
using System.Threading.Tasks;
#if Nancy
using Nancy.Hosting.Self;
#else
using Microsoft.Owin;
using Microsoft.Owin.Hosting;
using Owin;
using System.Web.Http;
using System.Net.Http.Formatting;
#endif


namespace 电子展板
{

    public class WebServer
    {

#if Nancy
        private static NancyHost _host;
#else 
        private static IDisposable host;
#endif


        public static void Start()
        {
#if Nancy
            _host = new NancyHost(new Uri("http://localhost:80"));
            _host.Start();
#else
            StartOptions startOptions = new StartOptions();
            startOptions.Urls.Add($"http://*:80/");
            host = WebApp.Start<Startup>(startOptions);
#endif 
        }

        public static void Stop()
        {
#if Nancy
            if (_host != null)
            {
                _host.Stop();
                _host.Dispose();
                _host = null;
            }
#else
             if (host != null)
             {
                 host.Dispose();
                 host = null;
             }
#endif
        }
    }

#if !Nancy
    /// <summary>
    /// Web启动类
    /// </summary> 
    public class Startup
    {
        private HttpConfiguration _config;
        /// <summary>
        /// 配置
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        public void Configuration(IAppBuilder app)
        {
            _config = new HttpConfiguration();
            _config.MapHttpAttributeRoutes();
            _config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
            _config.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("datatype", "json", "application/json"));
            //全局拦截
            app.Use<ResouceStaticRoute>("/static", "/Assets");
            app.UseWebApi(_config);
        }
    }

    public class ResouceStaticRoute : OwinMiddleware
    {
        private string route;
        private string resources;
        public ResouceStaticRoute(OwinMiddleware next, string route, string resources) : base(next)
        {
            this.route = route;
            this.resources = resources;
        }

        public override async Task Invoke(IOwinContext context)
        {
            try
            {
                string method = context.Request.Method;//GET POST
                string path = context.Request.Path.ToString();
                if (method.ToUpper() == "GET" && path.StartsWith(route))
                {
                    string resourePath = path.Replace(route, "");
                    string packUri = $"pack://application:,,,{resources}{resourePath}";
                    byte[] bytes = null;
                    using (Stream stream = System.Windows.Application.GetResourceStream(new Uri(packUri, UriKind.RelativeOrAbsolute)).Stream)
                    {
                        bytes = new byte[stream.Length];
                        stream.Read(bytes, 0, bytes.Length);
                    }

                    context.Response.ContentType = System.Web.MimeMapping.GetMimeMapping(path);
                    context.Response.Write(bytes, 0, bytes.Length);
                    await Task.FromResult(0);
                }
                await Next.Invoke(context);
            }
            catch (InvalidCastException ex)
            {
                await Next.Invoke(context);
            }
            catch (Exception ex)
            {
                await Next.Invoke(context);
            }
        }
    }
#endif
}

#if !Nancy
namespace Nancy.Swagger.Annotations.Attributes
{
    [AttributeUsage(AttributeTargets.Class, Inherited = true)]
    public class ModelAttribute : Attribute
    {
        public ModelAttribute(string description)
        {
            Description = description;
        }

        public string Description { get; set; }

        /// <summary>
        /// By default, only read/write props are shown, this 
        /// prop allows read only props to be shown.
        /// </summary>
        public bool ShowReadOnlyProps { get; set; }
    }

    public abstract class SwaggerDataTypeAttribute : Attribute
    {
        private long? _maximum;
        private long? _minium;
        private bool? _required;
        private bool? _uniqueItems;

        protected SwaggerDataTypeAttribute(string name)
        {
            Name = name;
        }

        public string Description { get; set; }

        public string DefaultValue { get; set; }

        public string[] Enum { get; set; }

        public long Maximum
        {
            get { return _maximum.GetValueOrDefault(); }
            set { _maximum = value; }
        }

        public long Minimum
        {
            get { return _minium.GetValueOrDefault(); }
            set { _minium = value; }
        }

        public string Name { get; set; }

        public bool Required
        {
            get { return _required.GetValueOrDefault(); }
            set { _required = value; }
        }

        public bool UniqueItems
        {
            get { return _uniqueItems.GetValueOrDefault(); }
            set { _uniqueItems = value; }
        }

        internal long? GetNullableMaximum()
        {
            return _maximum;
        }

        internal long? GetNullableMinimum()
        {
            return _minium;
        }

        internal bool? GetNullableRequired()
        {
            return _required;
        }

        internal bool? GetNullableUniqueItems()
        {
            return _uniqueItems;
        }
    }

    [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = true)]
    public class ModelPropertyAttribute : SwaggerDataTypeAttribute
    {
        public ModelPropertyAttribute() : this(null)
        {
        }

        public ModelPropertyAttribute(string name) : base(name)
        {
        }

        /// <summary>
        /// Ignore this property when generating swagger model.
        /// </summary>
        public bool Ignore { get; set; }
    }
}
#endif