using System;
using System.Text;
using System.Threading;
using System.Runtime.CompilerServices;
//using System.Threading;
//using System.Globalization;

using CommonHelpers;

namespace TypeInColor {

//**************************************************************************************************
static class Startup {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[MethodImpl(MethodImplOptions.NoInlining)]
static void PrepareToStart()
{
   HProgram.SpecifyMainThread();
   HConsole.Access();
   //Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
   //Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
}

static int Start(string[] args)
{
   int status = -1;
   Exception error = null;
   try
   {
      //Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
      //Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
      Program.Run( args );
      status = 0;
   }
   catch (Exception e)
   {
      status = e is HAppFailureException ? 1 : -1;
      error = e;
      string errorText = e is HAppFailureException ?
         HString.EmptyAsNull( e.Message ) :
         HException.ComposeChainedMessage( e, true );
      if ( errorText != null )
         HConsole.PrintError( errorText );
   }
   finally
   {
      try
      {
         //HGC.CollectAndWait();
      }
      catch (Exception e)
      {
         status = -1;
         if ( error == null )
            HConsole.PrintError( error = e );
      }
   }
   return status;
}


//--------------------------------------------------------------------------------------------------

/// <summary>
/// Application entry point
/// </summary>
static int Main(string[] args)
{
   try
   {
      PrepareToStart();
   }
   catch (Exception e)
   {
      try { Console.WriteLine( e ); return -1; }
      catch { throw; }
   }
// Setting console IO-encoding to Unicode by default (if possible):
   bool useUnicodeEncoding = true;
   Action restoreEncoding = null;
   if ( useUnicodeEncoding )
   {
      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) =>
         {
            Monitor.TryEnter( HConsole.SyncRoot, 100 );
            restoreEncoding();
            Console.WriteLine();
         };
      }
   }
   // Disabling interruption by Ctrl+C (but Ctrl+Break is always enabled):
   //Console.TreatControlCAsInput = true;
   try
   {
   // Calling "quasi-main" subroutine:
      return Start( args );
   }
   finally
   {
   // Restoring console IO-encoding from Unicode:
      restoreEncoding!.Invoke();
   }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // Startup
//**************************************************************************************************

} // TypeInColor
