using System;
using System.Runtime.CompilerServices;
using Microsoft.Extensions.Configuration;

using CommonHelpers;

namespace BookRegistry.Server {

//**************************************************************************************************
class StartupData {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

const string ConfigSectionName = "ServiceConfig";

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

/// <exception cref="InvalidOperationException" />
public static string ServerName =>
   _ServerName_ ?? throw PropertyNotInitializedError();
/// <exception cref="InvalidOperationException" />
public static string DatabaseName =>
   _DatabaseName_ ?? throw PropertyNotInitializedError();
/// <exception cref="InvalidOperationException" />
public static string DatabaseLanguage =>
   _DatabaseLanguage_ ?? throw PropertyNotInitializedError();
public static bool UseInvariantCulture =>
   _UseInvariantCulture_ ?? throw PropertyNotInitializedError();
/// <exception cref="InvalidOperationException" />
public static string UserPasswordMask =>
   _UserPasswordMask_ ?? throw PropertyNotInitializedError();

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

public StartupData(IConfiguration configuration) =>
   _Configuration_ = configuration;

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

/// <exception cref="OperationFailedException" />
public void ObtainConfigParameters()
{
   _ServerName_            = ObtainConfigParameter<string>( nameof(ServerName) );
   _DatabaseName_          = ObtainConfigParameter<string>( nameof(DatabaseName) );
   _DatabaseLanguage_      = ObtainConfigParameter<string>( nameof(DatabaseLanguage) );
   _UseInvariantCulture_   = ObtainConfigParameter<bool>( nameof(UseInvariantCulture) );
   _UserPasswordMask_      = ObtainConfigParameter<string>( nameof(UserPasswordMask) );
   //_..._ = ObtainConfigParameter<>( nameof(...) );
}

//--------------------------------------------------------------------------------------------------
/*
public static void Specify...(... value)
{
   _..._ = value;
}
*/
//--------------------------------------------------------------------------------------------------

public static OperationFailedException ConfigParameterError(
   string parameterName, string message ) =>
   OpFailedExceptionCreator.Create(
      "{0}\n"+
      "(Config.parameter: \"{1}\" from \"ServiceConfig\" section.)",
      message, parameterName );
public static OperationFailedException ConfigParameterError(
   string parameterName, string messageFmt, params object?[] parameters ) =>
   ConfigParameterError( parameterName, HString.FormatAsText( messageFmt, parameters ) );

public static OperationFailedException ConfigParameterError(string parameterName,Exception e) =>
   ConfigParameterError( parameterName, HException.GetErrorMessage(e) );

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

/// <exception cref="OperationFailedException" />
IConfigurationSection ConfigurationSection =>
   _ConfigurationSection_ ??
      (_ConfigurationSection_ = _Configuration_.GetSection( ConfigSectionName )) ??
         throw OpFailedExceptionCreator.Create(
            "Configuration section not found: \"{0}\".",
            ConfigSectionName );

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

/// <exception crwf="ArgumentException" />
/// <exception cref="OperationFailedException" />
[HOptionalResult]
R ObtainConfigParameter<R>(string parameterName,bool required=true)
{
   object? rslt = null;
   try {
      rslt = ConfigurationSection.GetValue( typeof(R), parameterName );
   }
   catch (Exception e) {
      throw OpFailedExceptionCreator.Create(
         "Can not obtain configuration parameter \"{0}\" (\"{1}\" section).\n"+
         "{2}", parameterName, ConfigSectionName,
         HException.GetErrorMessage(e) ); }
   if ( rslt==null && required )
      throw ConfigParamNotDefinedError( parameterName );
   return (R)rslt!;
}

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

static OperationFailedException ConfigParamNotDefinedError(string parameterName) =>
   OpFailedExceptionCreator.Create(
      "Configuration parameter \"{0}\" is not defined (\"ServiceConfig\" section).",
      parameterName );

/// <exception crwf="ArgumentNullException" />
static InvalidOperationException PropertyNotInitializedError( [CallerMemberName]
                                                              string? parameterName=null ) =>
   HInvOpExceptionCreator.Create(
      "Startup property \"{0}\" has not been initialized (\"ServiceConfig\" section).",
      HArgChecking.NN( parameterName ) );

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

IConfiguration
   _Configuration_;
IConfigurationSection?
   _ConfigurationSection_;

static string?
   _ServerName_, _DatabaseName_, _DatabaseLanguage_, _UserPasswordMask_;
static bool?
   _UseInvariantCulture_;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // StartupData
//**************************************************************************************************

} // BookRegistry.Server
