#if NETCORE

using System;
using System.Collections.Generic;
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;
using System.Net;
using System.Net.WebSockets;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Security.Authentication;

namespace Apewer.Web
{

    /// <summary>ASP.NET Core 服务器。</summary>
    public abstract class AspNetCoreServer : IDisposable
    {

        #region 通用。

        IHost _host;
        IHostBuilder _builder;

        private bool _running = false;

        /// <summary>正在运行。</summary>
        public bool Running { get => _running; }

        /// <summary>启动 Host。</summary>
        protected Exception Run<TStartup>(bool async) where TStartup : AspNetCoreStartup
        {
            try
            {
                _builder = Host.CreateDefaultBuilder().ConfigureWebHostDefaults((builder) =>
                {
                    Configure(builder);
                    builder.UseStartup<TStartup>();
                });

                // 运行。
                _host = _builder.Build();
                if (async) _host.RunAsync();
                else _host.Run();

                return null;
            }
            catch (Exception ex)
            {
                return ex;
            }
        }

        /// <summary>配置 WebHost 构建程序。</summary>
        protected abstract void Configure(IWebHostBuilder builder);

        /// <summary>启动。</summary>
        public abstract void Run<T>() where T : AspNetCoreStartup;

        /// <summary>释放非托管资源。</summary>
        public void Dispose()
        {
            RuntimeUtility.Dispose(_host);
            _host = null;
            _running = false;
        }

        #endregion

        #region 用于派生类的属性。

        private int _port = -1;
        private long _maxbody = 1073741824L;
        private X509Certificate2 _certificate = null;
        private SslProtocols _ssl = SslProtocols.Tls;

        /// <summary>监听的端口。默认值:自动选择 80 端口或 443 端口。</summary>
        public int Port
        {
            get { return (_port < 0) ? (_certificate == null ? 80 : 443) : _port; }
            set { if (!_running) _port = value.Restrict(0, 65535); }
        }

        /// <summary>使用的证书。默认值:无。</summary>
        public X509Certificate2 Certificate
        {
            get { return _certificate; }
            set { if (!_running) _certificate = value; }
        }

        /// <summary>请求的最大 Body 大小,单位为字节,最小为 1 MB。默认值:1073741824(1 GB)。</summary>
        public virtual long MaxBody
        {
            get { return _maxbody; }
            set { if (!_running) _maxbody = value.Restrict(1048576L, 1073741824L); }
        }

        /// <summary>使用 SSL 时的协议。默认值:TLS 1.0。</summary>
        public virtual SslProtocols SslProtocol
        {
            get { return _ssl; }
            set { if (!_running) _ssl = value; }
        }

        #endregion

    }

}

#endif