using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ITVisions.Code;
using ITVisions.Controllers;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ITVisions.Data;
using ITVisions.Models;
using ITVisions.Services;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Caching;
using Microsoft.AspNetCore.Session;
using Microsoft.AspNetCore.Rewrite;
using DotnetThoughts.AspNetCore;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using ASPNETCore_NETCore.BL;
using ASPNETCore_NETCore.Middleware;
using Microsoft.AspNetCore.Identity;

namespace ITVisions
{
 public class Startup
 {
  public Startup(IHostingEnvironment env)
  {
   var builder = new ConfigurationBuilder()
       .SetBasePath(env.ContentRootPath)
       .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
       .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

   if (env.IsDevelopment())
   {
    // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
   // TODO geht nicht mehr seit Update 2.0: builder.AddUserSecrets();
   }

   builder.AddEnvironmentVariables();
   Configuration = builder.Build();
  }

  public IConfigurationRoot Configuration { get; }

  // This method gets called by the runtime. Use this method to add services to the container.
  public void ConfigureServices(IServiceCollection services)
  {
   #region framework services.
   services.AddDbContext<ApplicationDbContext>(options =>
       options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

   services.AddIdentity<ApplicationUser, IdentityRole>()
       .AddEntityFrameworkStores<ApplicationDbContext>()
       .AddDefaultTokenProviders();

   services.AddMvc();
   services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
   #endregion

   // Add application services.
   services.AddTransient<IEmailSender, AuthMessageSender>();
   services.AddTransient<ISmsSender, AuthMessageSender>();

   // ================ Sitzungen konfigurieren
   services.AddMemoryCache();
   services.AddSession(o =>
   {
    o.CookieName = "IT-Visions.Cookie"; // Name festlegen
    o.IdleTimeout = TimeSpan.FromMinutes(10); // Timeout 10 Minuten
    o.CookieHttpOnly = false; // auch für Client-Skript verfügbar machen
   });

   #region Eigene Dienste in DI konfigurieren
   // ============== ab hier eigene Dienste
   // Transient: Jeder Nutzer kriegt eine eigene Instanz
   //services.AddTransient<FlugService>();
   //services.AddTransient<IFlugService, FlugService>();

   //services.AddSingleton<FlugService>();
   //services.AddSingleton<IFlugService, FlugService>();

   services.AddTransient<FlugManager>();
   services.AddScoped<FlugService>();
   services.AddTransient<IFlugService, FlugService>();

   // Singleton: Alle kriegen eine einzige Instanz
   services.AddSingleton(typeof(Application));
   // Eigener EF-Kontext
   services.AddDbContext<EFCore_Kontext.WWWingsContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("WWWingsConnection")));
   #endregion

   #region Konfiguration
   // Konfigurationsoption-Objekt nutzen
   services.AddOptions();
   // Alternative 1: Option-Objekt explizit befüllen
   //services.Configure<Autor>(o =>
   //{ o.Name = "HS"; o.Website = "www.IT-Visions.de"; }
   // );
   // Alternative 2: Option-Objekt aus appsettings.json befüllen
   services.Configure<Autor>(Configuration.GetSection("Autor"));
   #endregion

   services.AddResponseCaching();
  }

  // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
  {
   #region Standardfunktionen
   // Funktionen, die früher selbstverständlich waren, müssen nun aktiviert werden
   app.UseDefaultFiles();
   app.UseStaticFiles();
   //app.UseDirectoryBrowser();
   // Sessions aktivieren
   app.UseSession();
   #endregion

   #region Logging
   loggerFactory.AddConsole(Configuration.GetSection("Logging"));
   loggerFactory.AddDebug();
   #endregion

   #region Fehlerbehandlung
   if (env.IsDevelopment())
   {
    app.UseDeveloperExceptionPage();
    app.UseDatabaseErrorPage();
    app.UseBrowserLink();

    // oder:
    //app.UseExceptionHandler(errorApp =>
    //{
    // errorApp.Run(async context =>
    // {
    //  context.Response.StatusCode = 200;
    //  context.Response.ContentType = "text/plain";
    //  var error = context.Features.Get<IExceptionHandlerFeature>();
    //  if (error != null)
    //  {
    //   var ex = error.Error;
    //   await context.Response.WriteAsync("ASP.NET Core Exception Middleware:" + ex.ToString());
    //  }
    // });
    //});
   }
   else
   {
    app.UseExceptionHandler("/Home/Error");
   }


   #endregion

   #region Standardfunktionen
   // Funktionen, die früher selbstverständlich waren, müssen nun aktiviert werden
   app.UseDefaultFiles();
   app.UseStaticFiles();
   //app.UseDirectoryBrowser();
   // Sessions aktivieren
   app.UseSession();
   #endregion

   #region Authentifizierung
   app.UseIdentity();

   // Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
   #endregion

   #region Caching und Compression
   //app.UseResponseCaching();
   //app.UseResponseCompression(); // neu in 1.1!
   //app.UseHTMLMinification(); // https://github.com/anuraj/HtmlMinificationMiddleware
   #endregion

   #region Rewriting

   var options = new RewriteOptions()

 
   //.AddRedirect("(.*)/$", "$1")                    // Redirect using a regular expression
   //.AddRedirect("Fluege/(.*)/(.*)/(.*)", "WWWings/$1/$2/$3"); // test mit http://localhost:12345/Fluege/Rom/10/20
   .AddRewrite("Abflugort/(.*)/Paging/(.*)/(.*)", "WWWings/$1/$2/$3", true) // test mit http://localhost:12345/Fluege/Rom/10/20
            

   //.AddRewrite(@"app/(\d+)", "app?id=$1", skipRemainingRules: false); // Rewrite based on a Regular expression
                                                                            //.AddRedirectToHttps(302, 5001);                  // Redirect to a different port and use HTTPS
                                                                            //.AddIISUrlRewrite(env.ContentRootFileProvider, "UrlRewrite.xml")        // Use IIS UrlRewriter rules to configure
                                                                            //.AddApacheModRewrite(env.ContentRootFileProvider, "Rewrite.txt");       // Use Apache mod_rewrite rules to configure

.AddRedirect("von/(.*)/nach/(.*)", "flugset/$1/$2",301)
.AddRedirect("von(.*)/nach(.*)", "flugset/$1/$2", 301)
.AddRedirect("von/(.*)", "flugset/$1/*", 301)
.AddRedirect("nach/(.*)", "flugset/*/$1", 301)
.AddRewrite("von/(.*)/nach/(.*)", "flugset/$1/$2", true)
.AddRewrite("von(.*)/nach(.*)", "flugset/$1/$2", true)
.AddRewrite("von/(.*)", "flugset/$1/*", true)
.AddRewrite("nach/(.*)", "flugset/*/$1", true)

   ;
   app.UseRewriter(options); // neu in 1.1!
   #endregion

   #region Custom Middleware
   // so
   //app.UseMiddleware<ASPNETCore_NETCore.Middleware.RequestCultureMiddleware>();
   // oder so:
   //app.UseRequestCulture();
   #endregion

   #region MVC aktivieren (am Ende der Pipeline!)
   app.UseMvc(routes =>
{
 routes.MapRoute( // Standardroute controller/action/id?
                  name: "default",
                  template: "{controller=Home}/{action=Index}/{id?}");
});
   #endregion


  }
 }
}
