using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Hncore.Infrastructure.WebApi;
using Hncore.Pass.Manage.Configs;
using Hncore.Pass.Manage.Repository;
using Hncore.Pass.Manage.Util;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace Hncore.Pass.Manage
{
    /// <summary>
    /// 应用程序启动类(主要完成服务注册和中间件注册，构建HTTP请求管道)
    /// 应用启动流程：应用启动 -> Startup构造函数 -> ConfigureServices方法 -> Configure方法
    /// </summary>
    ///
    public class Startup
    {
        /// <summary>
        /// 配置信息对象
        /// </summary>
        public IConfiguration Configuration { get; }

        /// <summary>
        /// 构造函数(第1个被执行的函数)
        /// </summary>
        /// <param name="env">提供了当前应用程序的运行的宿主环境配置信息象</param>
        ///
        public Startup(IHostingEnvironment env)
        {
            /*
             appsettings.Development.json中配置了开发环境专用配置信息
             appsettings.Production.json中配置了生产环境专用配置信息
             appsettings.json保存了两个环境均会用到的公共配置信息
             此处主要是加载公共配置信息和专用配置信息，例如如果当前为
             开发模式，会加载appsettings.json和appsettings.Development.json两个文件中的配置信息
             生产模式，会加载appsettings.json和appsettings.Production.json两个文件中的配置信息
            */
            Configuration = env.UseAppsettings();
        }

        /// <summary>
        ///  服务配置，相当于Java项目中的spring.xml，用来将配置对象添加到容器中管理起来备用(第2个被执行的函数)
        /// </summary>
        /// <param name="services">服务集合对象(可以理解为内置的依赖注入容器)</param>
        /// <returns>构造好的服务提供对象</returns>       
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.Configure<AppSettings>(Configuration);//加载appsettiong.xxx.json中的配置信息到AppSettings对象中备用

            //添加EF数据库上下文对象
            services.AddDbContext<EfDbContext>(c => c.UseMySql(Configuration["MySql"]));

            //配置Redis
            RedisHelper.Initialization(new CSRedis.CSRedisClient(Configuration["Redis"]));

            //HttpClient配置
            services.AddHttpClient();

            services.MyServicesSpecialUseConfigure();//本Web应用专用配置

            //根据应用配置信息对象、编译版本、服务选项对象创建服务提供对象
            IServiceProvider result = services.Init(Configuration, CompatibilityVersion.Version_2_2, new ServiceOption
            {
                //启用全局授权过滤器(由ManageAuthFilter类具体实现)
                UseGlobalManageAuthFilter = false
            });
            return result;
        }

        /// <summary>
        /// 请求管道配置，可以将一些中间组件添加到app对象中
        /// </summary>
        /// <param name="app">用于构建应用程序的请求管道</param>
        /// <param name="env">提供了当前应用程序的运行的宿主环境配置信息</param>
        /// <param name="loggerFactory">日志工厂</param>
        ///
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime applicationLifetime)
        {
            //初始化应用程序构建器，启用NLog、统一错误异常处理、跨域请求、MVC等
            app.Init(loggerFactory, applicationLifetime);

          //  app.MySpecialUseConfigure(env, loggerFactory);//本Web应用专用配置
        }
    }
}