using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace CorsServer.WebApi31
{
    public class StartupConfig
    {
        public StartupConfig(IConfiguration configuration, IHostEnvironment hostingEnvironment, IWebHostEnvironment webHostEnvironment)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            //Config
            services.Configure<CorsOption>(Configuration.GetSection(ApplicationConst.CorsConfigOptionName));

            //CorsÅäÖÃÎļþÑ¡Ïî
            AddCors_Config(services);

            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IOptionsSnapshot<CorsOption> corsOtionsSnapshot)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseCors(ApplicationConst.DefaultPolicyName);

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

        private IServiceCollection AddCors_Config(IServiceCollection services)
        {
            services.AddCors(setup =>
              {
                  var corsOption = services.BuildServiceProvider().GetRequiredService<IOptionsSnapshot<CorsOption>>().Value;
                  setup.AddPolicy(ApplicationConst.DefaultPolicyName, builder =>
                  {
                      if (corsOption.Origins == null)
                      {
                          builder.SetIsOriginAllowed(_ => true);
                      }
                      else if (corsOption.Origins.Count == 0)
                      {
                          builder.SetIsOriginAllowed(_ => true);
                      }
                      else if (corsOption.Origins.Contains("*"))
                      {
                          builder.SetIsOriginAllowed(_ => true);
                      }
                      else
                      {
                          builder.WithOrigins(corsOption.Origins.ToArray());
                          builder.SetIsOriginAllowedToAllowWildcardSubdomains();
                      }

                      if (corsOption.Methods == null || corsOption.Methods.Count == 0)
                      {
                          builder.AllowAnyMethod();
                      }
                      else
                      {
                          builder.WithMethods(corsOption.Methods.ToArray());
                      }

                      if (corsOption.Headers == null || corsOption.Headers.Count == 0)
                      {
                          builder.AllowAnyHeader();
                      }
                      else
                      {
                          builder.WithMethods(corsOption.Headers.ToArray());
                      }

                      if (corsOption.ExposedHeaders != null && corsOption.ExposedHeaders.Count > 0)
                      {
                          builder.WithExposedHeaders(corsOption.ExposedHeaders.ToArray());
                      }

                      if (corsOption.AllowCredentials)
                      {
                          builder.AllowCredentials();
                      }
                      else
                      {
                          builder.DisallowCredentials();
                      }

                      if (corsOption.PreflightMaxAge.TotalSeconds > 0)
                      {
                          builder.SetPreflightMaxAge(corsOption.PreflightMaxAge);
                      }
                  });
              });

            return services;
        }
    }
}