using System;
using System.Text;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;

using CommonHelpers;

namespace BookRegistry.Server {

//**************************************************************************************************
static class ProgramStart {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static HConsole CON => HConsole.StdConIO;
//==================================================================================================
// These two property are needed because static web assets still demand development environment (for capability to work).
// Development environment is simlated in “PrepareToStart” static method (for the sake of development static web assets).
// (If static web assets feature will be corrected, there will be no need in these properties so as and in dev.environment simulation.)
public static bool IsDevelopmentEnvironment { get; private set; }
public static string EnvironmentName { get; private set; } = "";
//==================================================================================================

// Service entry-point routine:
static int Main(string[] args)
{
   try {
      PrepareToStart();
   }
   catch ( Exception e ) {
      Console.WriteLine( e.ToString() );
      return 1; // failure
   }
   // Setting console IO-encoding to Unicode (if possible):
   bool useUnicodeEncoding = true;
   Action? restoreEncoding = null;
   Encoding
      inputEncoding = Console.InputEncoding,
      outputEncoding = Console.OutputEncoding;
   try { Console.OutputEncoding = Encoding.Unicode; }
   catch { useUnicodeEncoding = false; }
   if ( useUnicodeEncoding )
      try { Console.InputEncoding = Encoding.Unicode; }
      catch { useUnicodeEncoding = false; Console.OutputEncoding = outputEncoding; }
   if ( useUnicodeEncoding )
   {
      restoreEncoding = ()=>{
         Console.InputEncoding = inputEncoding;
         Console.OutputEncoding = outputEncoding; };
      Console.CancelKeyPress += (sender,cancelEventArgs) => restoreEncoding();
   }
   try {
      // Calling "quasi-main" subroutine:
      return Start( args );
   }
   finally {
      // Restoring console IO-encoding from Unicode:
      restoreEncoding?.Invoke();
   }
}

//==================================================================================================

[MethodImpl(MethodImplOptions.NoInlining)]
static void PrepareToStart()
{
// Saving environment name and dev.environment flag (while static web assets are not corrected):
EnvironmentName = HString.SubstNullOrEmpty(
   Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), "Production" );
IsDevelopmentEnvironment = HString.Equals( EnvironmentName, "Development", true );
   // Initialization (optional, but useful):
   CommonHelpersLibrary.Initialize(
      //CommonHelpersInitFlags.InteractsWithDesktop |
      CommonHelpersInitFlags.StandaloneServiceDefaults
      //CommonHelpersInitFlags.InteractiveConsoleApplicationDefaults |
      //CommonHelpersInitFlags.IgnoreRaiseOnUnhandledExceptionUnderDebugger |
   );
#if DEBUG
   // This is in order to use fatal error message box in case of fatal breakdown.
   // Such system GUI-box is possible only in Win32-version of CommonHelpers library.
   // In any way, the library attempts to open such an error in browser
   // (specially prepared html-file in associated program).
   // This behaviour is switched on later in "Startup.Configure" —
   // for "Development" and/or "DebugExpose" (environments) + DEBUG-compilation.
   string? aspNetCoreEnvironment = Environment.GetEnvironmentVariable( "ASPNETCORE_ENVIRONMENT" );
   if ( HString.Equals( aspNetCoreEnvironment, "Development", true ) || // case insensitive
        HString.Equals( aspNetCoreEnvironment, "DebugExpose", true ) )  // case insensitive
      HProgram.SpecifyInteractsWithDesktop();
#endif // DEBUG
// Simulating development environment (for the sake of development static web assets):
Environment.SetEnvironmentVariable( "ASPNETCORE_ENVIRONMENT", "Development" );
}

[MethodImpl(MethodImplOptions.NoInlining)]
static int Start(string[] args)
{
   CON.UsePendingNewLine = true;
   CON.PrintHeader(
      "BookRegistry app. Web-service (Blazor_WASM+TS+ADO+TSQL) | {0}:",
      BookRegistry_Server_Info.CopyrightString );
   CON.PrintOperation( "The server is starting" );
   IHost host;
   try {
   // Startup::ConfigureServices is called here.
   // Startup::Configure is NOT called here, but in another thread.
      host = CreateHostBuilder( args ).Build();
   }
   catch (Exception e) {
   throw; // to rely on active unhandled exception handler routine (from CommonHelpers library)
#pragma warning disable 162 // unreachable code
      CON.PrintError( HException.ComposeChainedMessage( e, true ) );// with stack trace;
      return HProgram.BreakdownExitCode; // -1 (default value)
#pragma warning restore 162 // unreachable code
   }
   host.Run(); // run incoming query processing (listener)
   CON.PrintFooter( "BookRegistry.Server Web-service is off." );
   return HProgram.SuccessfulExitCode; // 0 (default value)
}

//==================================================================================================

static IHostBuilder CreateHostBuilder(string[] args) =>
   Host.CreateDefaultBuilder( args )
      .ConfigureWebHostDefaults( webBuilder => {
         webBuilder.UseStartup<Startup>();
      });

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // ProgramStart
//**************************************************************************************************

} // BookRegistry.Server
