using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using ClaimsSample.Extensions;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace ClaimsSample
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {

            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(options =>
                {
                    options.LoginPath = "/home/login";
                    options.AccessDeniedPath = "/home/AccessDenied";
                });

            var commonPolicy = new AuthorizationPolicyBuilder().RequireClaim("MyType").Build();

            services.AddAuthorization(options =>
            {
                options.InvokeHandlersAfterFailure = true;

                options.AddPolicy("common", commonPolicy);

                options.AddPolicy("User", policy => policy.RequireAssertion(context => context.User.HasClaim(c => (c.Type == "EmployeeNumber" || c.Type == "Role"))));

                //options.AddPolicy("RequireAdminAndDemoRole",policy=>policy.RequireRole("管理组").RequireRole("演示组"));
                //options.AddPolicy("RequireAdminAndDemoRole",policy=>policy.RequireRole("管理组","演示组"));
                //options.AddPolicy("RequireEmailClaim", policy => policy.RequireClaim(ClaimTypes.Email));
                //options.AddPolicy("RequireEmailClaimInAdminEmail", policy => policy.RequireClaim(ClaimTypes.Email,"admin@xcode.me","manager@xcode.me"));
                //options.AddPolicy("RequireUserNameIsAdmin",policy=> policy.RequireUserName("admin@xcode.me"));
                //options.AddPolicy("RequireUserAuthed", policy => policy.RequireAuthenticatedUser());
                //options.AddPolicy("RequireFunc", policy => policy.RequireAssertion(context => context.User.HasClaim(c => c.Type == ClaimTypes.Email && c.Value.EndsWith("@xcode.me") || c.Type == ClaimTypes.Name && c.Value == "admin")));

                //options.AddPolicy("AgeMin22", policy => policy.AddRequirements(new MinimumAgeRequirement(18)));

                //options.AddPolicy("customPolicy", policy => policy.RequireRole("开发部").RequireMinimumAge(18).AddRequirements(new ReadPermissionRequirement()).Combine(commonPolicy));

                //options.AddPolicy("RequireFunc", policy => policy.RequireAssertion(context => context.User.Identity.Name.EndsWith("xcode.me")));

            });

            services.AddSingleton<IAuthorizationHandler, MinimumAgeRequirement>();

            services.AddSingleton<IAuthorizationHandler, PermissionHandler>();

            services.AddSingleton<IAuthorizationPolicyProvider, MinimumAgePolicyProvider>();

            services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddRazorPagesOptions(options =>
                {
                    options.Conventions.AuthorizePage("/Contact", "RequireFunc");
                    options.Conventions.AuthorizeFolder("/Users", "RequireFunc");
                    options.Conventions.AllowAnonymousToFolder("/News");
                    options.Conventions.AllowAnonymousToPage("/News");

                    options.Conventions.AuthorizeAreaFolder("Identity", "/Manage", "customPolicy");
                });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseAuthentication();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();
            app.UseCookiePolicy();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
