using System;
using System.Text;

using CommonHelpers;

namespace SqlToCsvExport {

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

/// <summary>
/// Preprocessor for insertions / environment variables: $(IdentASCII) (analogically to SQLCMD)
/// </summary>
/// <exception cref="ArgumentNullException" />
/// <exception cref="OperationFailedException" />
string ProcessScriptLine(string str,int strNo)
{
   HArgChecking.VerifyNotNull( str );

   int len = str.Length, i = 0;
   while (i<str.Length && str[i]==' ') i++;
   if (i<=len-2 && str[i]=='-' && str[i+1]=='-')
      return str;

   if ( UseInsertionDef( str, strNo ) )
      return "--" + str;

   int pos = -1;

   OperationFailedException ErrorReporter( string baseText )
   {
      return ErrorReporterEx( baseText, pos );
   };
   OperationFailedException ErrorReporterEx( string baseText, int position )
   {
      return OpFailedExceptionCreator.Create(HLocal.TEXT(
         "{0}; line: {1} (position: {2}).",
         "{0}; в строке {1} (позиция {2})." ),
         baseText, strNo, position + 1 );
   };

   int insertionPos = -1;
   var sb = new StringBuilder();
   while ( ++pos < str.Length )
   {
      char ch = str[ pos ];
      switch ( ch )
      {
      case '$':
         if ( insertionPos < 0 )
         {
            if ( pos+1 < len && str[pos+1] == '(' )
               insertionPos = pos;
         }
         else
            throw ErrorReporter(HLocal.TEXT(
               "Unexpected character \"$\" of environment variable insertion",
               "Неожиданный символ \"$\" вставки переменной стреды" ));
         break;
      case '(':
         if ( insertionPos < 0 )
            break;
         if ( pos > insertionPos + 1 )
            throw ErrorReporter(HLocal.TEXT(
               "Unexpected character \"(\" in environment variable insertion",
               "Неожиданный символ \"(\" во вставке переменной стреды" ));
         break;
      case ')':
         if ( insertionPos < 0 )
            break;
         if ( pos == insertionPos + 1 )
            throw ErrorReporter(HLocal.TEXT(
               "Unexpected character \")\" in opening of environment variable insertion",
               "Неожиданный символ \")\" при открытии вставки переменной стреды" ));
         if ( pos == insertionPos + 2 )
            throw ErrorReporterEx(HLocal.TEXT(
               "Attempt of insertion of environment variable with empty name",
               "Попытка вставки переменной среды с пустым именем" ),
               insertionPos );
         string
            variableName = str.Substring( insertionPos + 2, pos - insertionPos - 2 ),
            variableValue = null;
         try
         {
            if ( !IsNormalAsciiIdent( variableName ) )
               throw OpFailedExceptionCreator.Create(HLocal.TEXT(
                  "Incorrect ASCII identifier: \"{0}\".",
                  "Некорректный идентификатор ASCII: \"{0}\"." ),
                  variableName );
            if ( !InsertionDictionary.TryGetValue( variableName, out variableValue ) )
            {
               variableValue = Environment.GetEnvironmentVariable( variableName );
               if ( variableValue == null )
                  throw OpFailedExceptionCreator.Create(HLocal.TEXT(
                     "Inserted environment variable is not defined or empty: $({0}).",
                     "Вставляемая переменная среды не определена либо пустая: $({0})." ),
                     variableName );
            }
         }
         catch (Exception e)
         {
            throw OpFailedExceptionCreator.Create(HLocal.TEXT(
               "Error during attempt of environment variable insertion in line {0} "+
               "(position: {1}).\n"+
               "{2}",
               "Ошибка вставки переменной среды в строке {0} "+
               "(позиция {1}).\n"+
               "{2}" ),
               strNo, insertionPos + 1, e.Message );
         }
         sb.Append( variableValue );
         insertionPos = -1;
         continue;
      default:
         if ( insertionPos >= 0 && pos == insertionPos + 1 )
            throw ErrorReporter(HLocal.TEXT(
               "Character \"(\" was expected, as continuation of environment variable insertion",
               "Ожидался символ \"(\" продолжения открытия вставки переменной стреды" ));
         break;
      }
      if ( insertionPos < 0 )
         sb.Append( ch );
   } // while
   if ( insertionPos >= 0 )
      throw ErrorReporter(HLocal.TEXT(
         "Unclosed insertion of environment variable",
         "Незакрытая вставка переменной стреды" ));
   return sb.ToString();
}

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

} // SqlToCsvExport
