//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// CommonHelpers satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define TRACE
#define DEBUG

using System;
using System.Diagnostics;

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

//**************************************************************************************************
class Tracer {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public Tracer(bool debug)
{
   _Debug_ = debug;
}

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

public void Print()
{
   Print("");
}

public void Print(string message)
{
   Print(HTraceMessageCategory.Neutral,message);
}

public void Print(string messageFmt,params object[] parameters)
{
   Print(HTraceMessageCategory.Neutral,string.Format(messageFmt,parameters));
}

public void Print(object obj)
{
   Print(HTraceMessageCategory.Neutral,obj.ToString());
}

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

public void Print(HTraceMessageCategory messageCategory,string message)
{
   bool isActiveCategory = messageCategory != HTraceMessageCategory.None;
#if RELEASE
   if ( !isActiveCategory )
      return;
#endif // RELEASE
   lock (_StaticSyncRoot_)
   {
      bool dotNetTrace = !HCompilationCH.IsWin32;
      int indentLevel = dotNetTrace ? Trace.IndentLevel : 0;
#if DEBUG
      if ( isActiveCategory )
#endif // DEBUG
      if ( dotNetTrace )
         if (_Debug_)
            Debug.IndentLevel = 0;
         else
            Trace.IndentLevel = 0;
      try
      {
         string outputString = HString.FormatAsText(
            "{0}{1}{2} >> {3}",
            HOps.Exchange(ref _WasPrinted_,true) ? "" : Environment.NewLine,
            CommonHelpersLibrary.IsWASM ? "" : (HProgram.MainModuleName+" "),
            GetMessageCategotyChar( messageCategory ),
            message );
#if DEBUG
         if ( isActiveCategory )
#endif // DEBUG
         if ( dotNetTrace )
            if (_Debug_)
            {
               Debug.WriteLine( outputString );
               Debug.Flush();
            }
            else
            {
               Trace.WriteLine( outputString );
               Trace.Flush();
            }
         else
            Win32_Core.OutputDebugString( outputString );
      }
      finally
      {
#if DEBUG
         if ( isActiveCategory )
#endif // DEBUG
         if ( dotNetTrace )
            if (_Debug_)
               Debug.IndentLevel = indentLevel;
            else
               Trace.IndentLevel = indentLevel;
      }
   }
}

public void Print( HTraceMessageCategory messageCategory,
                   string messageFmt, params object[] parameters )
{
   Print(messageCategory,string.Format(messageFmt,parameters));
}

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

public void PrintInformation(string message)
{
   Print(HTraceMessageCategory.Information,message);
}

public void PrintInformation(string messageFmt,params object[] parameters)
{
   Print(HTraceMessageCategory.Information,string.Format(messageFmt,parameters));
}

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

public void PrintWarning(string message)
{
   Print(HTraceMessageCategory.Warning,message);
}

public void PrintWarning(string messageFmt,params object[] parameters)
{
   Print(HTraceMessageCategory.Warning,string.Format(messageFmt,parameters));
}

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

public void PrintError(string message)
{
   Print(HTraceMessageCategory.Error,message);
}

public void PrintError(string messageFmt,params object[] parameters)
{
   Print(HTraceMessageCategory.Error,string.Format(messageFmt,parameters));
}

public void PrintError(Exception e)
{
   PrintError(e.Message);
}

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

public void PrintOperation(string message)
{
   PrintOperation(false,message);
}

public void PrintOperation(string messageFmt,params object[] parameters)
{
   PrintOperation(false,messageFmt,parameters);
}

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

public void PrintOperation(bool informationCategory,string message)
{
   Print( informationCategory ?
      HTraceMessageCategory.Information :
      HTraceMessageCategory.Neutral,
      "* {0} ...", message );
}

public void PrintOperation( bool informationCategory,
                            string messageFmt,
                            params object[] parameters )
{
   PrintOperation(informationCategory,string.Format(messageFmt,parameters));
}

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

public void DetailedPrint(string caption,string details)
{
   DetailedPrint(HTraceMessageCategory.Neutral,caption,details);
}

public void DetailedPrint(string caption,string detailsFmt,params object[] parameters)
{
   DetailedPrint(HTraceMessageCategory.Neutral,caption,detailsFmt,parameters);
}

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

public void DetailedPrint(HTraceMessageCategory messageCategory,string caption,string details)
{
   Print(messageCategory,"{0}: \"{1}\".",caption,details);
}

public void DetailedPrint( HTraceMessageCategory messageCategory, string caption,
                           string detailsFmt, params object[] parameters )
{
   DetailedPrint(messageCategory,caption,string.Format(detailsFmt,parameters));
}

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

public void DetailedPrintInformation(string caption,string details)
{
   DetailedPrint(HTraceMessageCategory.Information,caption,details);
}

public void DetailedPrintInformation(string caption,string detailsFmt,params object[] parameters)
{
   DetailedPrint(HTraceMessageCategory.Information,caption,detailsFmt,parameters);
}

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

public void DetailedPrintWarning(string caption,string details)
{
   DetailedPrint(HTraceMessageCategory.Warning,caption,details);
}

public void DetailedPrintWarning(string caption,string detailsFmt,params object[] parameters)
{
   DetailedPrint(HTraceMessageCategory.Warning,caption,detailsFmt,parameters);
}

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

public void DetailedPrintError(string caption,string details)
{
   DetailedPrint(HTraceMessageCategory.Error,caption,details);
}

public void DetailedPrintError(string caption,string detailsFmt,params object[] parameters)
{
   DetailedPrint(HTraceMessageCategory.Error,caption,detailsFmt,parameters);
}

public void DetailedPrintError(HTraceMessageCategory messageCategory,string caption,Exception e)
{
   DetailedPrintError(caption,e.Message);
}

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

static char GetMessageCategotyChar(HTraceMessageCategory messageCategory)
{
   switch (messageCategory)
   {
   case HTraceMessageCategory.None       : return '\0';
   case HTraceMessageCategory.Neutral    : return HUnicode.EmDash; //'-';
   case HTraceMessageCategory.Information: return 'I';
   case HTraceMessageCategory.Warning    : return 'W';
   case HTraceMessageCategory.Error      : return 'E';
   }
   throw HArgChecking.ArgumentException_IncorrectArguments;
}

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

bool
   _Debug_;

static bool
   _WasPrinted_;

static readonly object
   _StaticSyncRoot_ = new object();

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // Tracer
//**************************************************************************************************

} // CommonHelpers (.WASM)
