using System;
using System.Text;

using CommonHelpers;

namespace SqlCatPP {

//**************************************************************************************************
partial class Scripter {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <summary>
/// R-directive body extraction (string unfolding with a glance to environment)
/// </summary>
/// <remarks>
/// Method rerunts unfolded string result.
/// (This routine is called from PP-directive line.)
/// </remarks>
/// <exception cref="ArgumentNullException" />
/// <exception cref="InvalidOperationException" />
/// <exception cref="SqlPPException" />
string UnfoldRDirectiveBody(string str)
{
   HArgChecking.VerifyNotNull( str );
   if ( !Program.ProcessDirectives )
      throw new InvalidOperationException(
         "“ParseSqlDirective”-routine requires “ProcessDirectives”-property "+
         "to have “true”-value." );
   if ( str.IndexOf( '"' ) >= 0 )
      throw IncorrectRDirective_Error();

   var sb = new StringBuilder( str );
   int varIgnorationZoneEnd = -1;
   char ch = '\0';
   for ( int p=0; p<sb.Length; p++ )
   {
      char prevCh = ch;
      ch = sb[ p ];

      if ( varIgnorationZoneEnd >= 0 && p > varIgnorationZoneEnd )
         varIgnorationZoneEnd = -1;

      if ( varIgnorationZoneEnd < 0 &&
           ch=='$' && p+1<sb.Length && sb[ p+1 ]=='(' )
      {
         int closeBraketPos = -1;
         var varNameBldr = new StringBuilder();
         for ( int i=p+2; i<sb.Length; i++ )
            if ( sb[i]==')' ) { closeBraketPos = i; break; }
            else varNameBldr.Append( sb[i] );
         if ( closeBraketPos < 0 )
            throw IncorrectRDirective_Error();
         var variableName = varNameBldr.ToString();
         if ( !IsNormalAsciiIdent( variableName ) )
            if ( Program.ProcessDirectives )
               throw NotAsciiInsertion_Error( variableName );
         if ( !_SetVariables_.TryGetValue( variableName, out string variableValue ) )
            variableValue = Environment.GetEnvironmentVariable( variableName );
         if ( variableValue == null )
            throw InsertionVariableNotDef_Error( p, variableName );
         sb.Remove( p, closeBraketPos-p+1 );
         sb.Insert( p, variableValue );
         varIgnorationZoneEnd = p + variableValue.Length - 1;
      }
   }
   return sb.ToString();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // Scripter
//**************************************************************************************************

} // SqlCatPP
