using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

using CommonHelpers;

namespace BookRegistry.Server {

//**************************************************************************************************
public abstract partial class XControllerBase: ControllerBase {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class CurrentInfo
{
   public readonly string ActionName, MethodNameOrSignature;
   /// <exception cref="ArgumentException" />
   public CurrentInfo(Type controllerMethodType,string methodNameOrSignature)
   {
      if ( !HType.IsTypeOf<XControllerBase>( controllerMethodType ) )
         throw new ArgumentException(
            $"Controller type of method was expected: \"{nameof(XControllerBase)}\" "+
            "(for action name).",
            nameof( controllerMethodType ) );
      ActionName = controllerMethodType.Name;
      MethodNameOrSignature = methodNameOrSignature;
   }
} // CurrentInfo
//**************************************************************************************************
protected static HConsole CON => HConsole.StdConIO;
protected const string
   General_Role = ServiceRoleNames.General,
   Admin_Role = ServiceRoleNames.Administrator;
//==================================================================================================

[HAsyncStatic][HThreadStatic]
protected virtual void OnPrepareContext()
{}

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

[HAsyncStatic]
static void PrintInMethod() =>
   CON.PrintOperation( "[{0}] {1}", CurrentActionName, CurrentMethodNameOrSignature );

/// <exception cref="ArgumentNullException" />
[HAsyncStatic]
static void ReportException([HRequired] Exception? e)
{
   e = HArgChecking.NN( e );
   string errorMessage = HException.ComposeChainedMessage( e, true ); // with stack trace
   HTrace.PrintError( "Exception in [{0}] {1}:\n{2}",
      CurrentActionName, CurrentMethodNameOrSignature, errorMessage );
   CON.PrintError( errorMessage );
}

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

/// <exception cref="InvalidOperationException" />
[HAsyncStatic] static string CurrentActionName => ActionContext.ActionName;
/// <exception cref="InvalidOperationException" />
[HAsyncStatic] static string CurrentMethodNameOrSignature => ActionContext.MethodNameOrSignature;

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

/// <exception cref="InvalidOperationException" />
[HAsyncStatic][HStrictResult]
static CurrentInfo ActionContext => VerifyActive();

[HAsyncStatic]
static CurrentInfo VerifyActive()
{
   var info = _AsyncLocalInfo_.Value;
   if ( info == null )
      throw new InvalidOperationException(
         "Action operation is not active (\"XControllerBase\")." );
   return info;
}

/// <exception cref="InvalidOperationException" />
[HAsyncStatic]
static void VerifyNotActive()
{
   if ( _AsyncLocalInfo_.Value != null )
      throw new InvalidOperationException(
         "Attempt to repeatedely open action operation (\"XControllerBase\")." );
}

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

void BeginDo(string methodNameOrSignature)
{
   VerifyNotActive();
   OnPrepareContext();
   _AsyncLocalInfo_.Value = new CurrentInfo( GetType(), methodNameOrSignature );
   PrintInMethod();
}

void EndDo()
{
   _AsyncLocalInfo_.Value = null;
   QueryContext.Reset();
   CON.FlushPendingNewLine();
}

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

static readonly AsyncLocal<CurrentInfo?>
   _AsyncLocalInfo_ = new AsyncLocal<CurrentInfo?>();

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // XControllerBase
//**************************************************************************************************

} // BookRegistry.Server
