//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// CommonHelpers satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
using System.IO;
using System.Reflection;
using System.Diagnostics;
using System.Threading;
using System.ComponentModel;

#if !WASM
namespace CommonHelpers {
#else
namespace CommonHelpers.WASM {
#endif

//**************************************************************************************************
/// <summary>
/// </summary>
public static partial class HProgram {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <exception cref="InvalidOperationException" />
[HNotNull]
public static string SimpleName
{
   get { return Path.GetFileNameWithoutExtension( MainModuleName ); }
}

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

public static bool IsMainModuleNameSpecified
{
   get { return _MainModuleName_!=null; }
}

/// <exception cref="InvalidOperationException" />
[HNotNull]
public static string MainModuleName
{
   get
   {
      string mainModuleName =
         _MainModuleName_;
      if (mainModuleName!=null)
         return mainModuleName;
      var entryAssembly =
         Assembly.GetEntryAssembly();
      return entryAssembly!=null ?
         entryAssembly.ManifestModule.Name :
         ProcessModuleName;
      throw new InvalidOperationException(
         "Main program module name was not specified." );
   }
}

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

public static bool IsMainThreadSpecified
{
   get { return _MainThread_!=null; }
}

/// <exception cref="InvalidOperationException" />
[HNotNull]
public static Thread MainThread
{
   get
   {
      var result = _MainThread_;
      if (result!=null) return result;
      throw new InvalidOperationException(
         "Main program thread was not specified." );
   }
}

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

public static bool AreEntryPointArgumentsSpecified
{
   get { return _EntryPointArguments_ != null; }
}

public static bool HasEntryPointArguments
{
   get
   {
      return EntryPointArgumentCount > 0;
   }
}

public static int EntryPointArgumentCount
{
   get
   {
      return GetEntryPointArgCountFromCommandLine();
   }
}

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

public static string MainModuleNameSpecification
{
   get { return _MainModuleName_; }
}

public static void SpecifyMainModuleName([HOptional] string value)
{
   _MainModuleName_ = value;
}

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

public static bool IsInMainThread
{
   get { return MainThread == Thread.CurrentThread; }
}

public static Thread MainThreadSpecification
{
   get { return _MainThread_; }
}

public static void SpecifyMainThread()
{
   SpecifyMainThread( Thread.CurrentThread );
}

public static void SpecifyMainThread([HOptional] Thread value)
{
   _MainThread_ = value;
}

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

/// <exception cref="InvalidOperationException" />
public static void VerifyInMainThread()
{
   if ( !IsInMainThread )
      throw new InvalidOperationException(
         "Current thread is not main program thread." );
}
/// <exception cref="InvalidOperationException" />
public static void VerifyNotInMainThread()
{
   if ( IsInMainThread )
      throw new InvalidOperationException(
         "Operation can not be performed in main program thread." );
}

public static bool IsMainThread(Thread thread)
{
   return thread == MainThread;
}

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

public static string[] GetEntryPointArguments()
{
   return _EntryPointArguments_ ?? GetEntryPointArgsFromCommandLine();
}

public static string[] EntryPointArgumentsSpecification
{
   get { return _EntryPointArguments_; }
}

public static void SpecifyEntryPointArguments([HOptional] string[] value)
{
   _EntryPointArguments_ = value;
}

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

internal static void Access()
{}

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

static HProgram()
{
   CommonHelpers_Core.Access();
}

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

static readonly object
   _SyncRoot_ = new object(),
   _ExitSyncObject_ = new object();

static volatile string
   _MainModuleName_;
static volatile Thread
   _MainThread_;
static volatile string[]
   _EntryPointArguments_;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HProgram
//**************************************************************************************************

} // CommonHelpers (.WASM)
