#if NETCORE

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using System.Threading.Tasks;

namespace Apewer.Web
{

    /// <summary></summary>
    public abstract class AspNetCoreStartup
    {

        /// <summary>处理 WebSocket 请求。</summary>
        /// <remarks>默认值:FALSE。</remarks>
        public virtual bool UseWebSocket { get; protected set; } = false;

        /// <summary>WebSocket 保持活动的间隔时间,单位为秒。</summary>
        /// <remarks>默认值:10。</remarks>
        public virtual int KeepAlive { get; protected set; } = 10;

        /// <summary>处理请求。</summary>
        /// <param name="context"></param>
        public abstract void OnContext(HttpContext context);

        /// <summary>处理 WebSocket 请求。</summary>
        public virtual void OnWebSocket(HttpContext context, System.Net.WebSockets.WebSocket webSocket) { }

        #region Runtime

        bool _usedWebSocket = false;
        IConfiguration _configuration;

        /// <summary></summary>
        public AspNetCoreStartup() { }

        /// <summary></summary>
        public AspNetCoreStartup(IConfiguration configuration) => _configuration = configuration;

        /// <summary>使用此方法添加服务到容器。</summary>
        /// <remarks>此方法由运行时调用。</remarks>
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        }

        /// <remarks>此方法由运行时调用。</remarks>
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment()) app.UseDeveloperExceptionPage();

            _usedWebSocket = UseWebSocket;
            if (_usedWebSocket)
            {
                var wsOptions = new WebSocketOptions();
                var keepAlive = KeepAlive;
                if (keepAlive > 0) wsOptions.KeepAliveInterval = TimeSpan.FromSeconds(keepAlive);
                app.UseWebSockets(wsOptions);
            }

            app.Run(Handler);
        }

        Task Handler(HttpContext context)
        {
            try
            {
                if (_usedWebSocket && UseWebSocket)
                {
                    if (context.WebSockets.IsWebSocketRequest)
                    {
                        using (var ws = context.WebSockets.AcceptWebSocketAsync())
                        {
                            OnWebSocket(context, ws.Result);
                        }
                        return Task.CompletedTask;
                    }
                }

                OnContext(context);
            }
            catch { }
            return Task.CompletedTask;
        }

        #endregion

    }

}

#endif