using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Globalization;

using System.Data;
using System.Data.SqlClient;

using CommonHelpers;

namespace SqlToCsvExport {

//**************************************************************************************************
static partial class Program {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <exception cref="OperationFailedException" />
static void DownloadData()
{
   if ( InvolveScriptFile )
      HConsole.PrintOperation(HLocal.TEXT(
         "Executing script: \"{0}\"",
         "Выполнение скрипта: \"{0}\"" ),
         ScriptSource );
   else
      HConsole.PrintOperation(HLocal.TEXT(
         "Executing stored procedure: [{0}]",
         "Выполнение хранимой процедуры: [{0}]" ),
         ScriptSource );

   string scriptText = null;
   if ( InvolveScriptFile )
   {
      OpFailedExceptionCreator.Do(delegate{
         scriptText = new Scripter().LoadNParse( ScriptSource );
      });
      if ( string.IsNullOrWhiteSpace( scriptText ) )
         throw OpFailedExceptionCreator.Create(HLocal.TEXT(
            "Script is empty (does not contain significant SQL-lines): \"{0}\".",
            "Скрипт пустой (не содержит значимых строк SQL): \"{0}\"." ),
            ScriptSource );
   }
   else
      scriptText = string.Format( "exec [{0}]{1}", ScriptSource,
         !string.IsNullOrEmpty( ExtendedArgument ) ? " "+ExtendedArgument : "" );

   var cmd = new SqlCommand( scriptText, Connection )
   {
      CommandType = CommandType.Text,
      CommandText = scriptText,
      CommandTimeout = 0
   };

   SqlDataReader reader = null;
   StreamWriter writer = null;
   Exception error = null;
   try
   {
      reader = cmd.ExecuteReader( InvolveScriptFile ?
         CommandBehavior.SingleResult : CommandBehavior.Default );

      string resultFile = null;
      if ( InvolveStoredProc )
      {
         if ( reader.FieldCount != 1 || reader.GetName( 0 ) != "CSVBaseName" )
            throw new OperationFailedException(HLocal.TEXT(
               "Incorrect structure of 1-st result set (metadata).\n"+
               "CSV-file base name field not found: \"CSVBaseName\".",
               "Некорректная структура первого резалт-сета.\n"+
               "Поле базового имени CSV-файла не обнаружено: \"CSVBaseName\"." ));
         string csvBaseName;
         if ( !reader.Read() || (csvBaseName = reader[ 0 ].ToString().Trim()) == "" )
            throw new OperationFailedException(HLocal.TEXT(
               "CSV-file base name was not transferred by stored procedure "+
               "(1-st result set; field: \"CSVBaseName\").",
               "Базовое имя CSV-файла хранимой процедурой не передано "+
               "(1-й резалт-сет; поле \"CSVBaseName\")." ));
         try
         {
            if ( Path.GetDirectoryName( csvBaseName ) != "" )
               throw new HUnsuccessException();
         }
         catch (Exception e)
         {
            if ( e is ArgumentException || e is PathTooLongException || e is HUnsuccessException )
               throw HUnsuccessExceptionCreator.Create(HLocal.TEXT(
                  "Incorrect CSV-file base name: \"{0}\" (field: \"CSVBaseName\").",
                  "Некорректное базовое имя CSV-файла: \"{0}\" (поле \"CSVBaseName\")." ),
                  csvBaseName );
            throw;
         }
         resultFile = csvBaseName + ".csv";

         if ( !reader.NextResult() )
            throw new OperationFailedException(HLocal.TEXT(
               "2-nd result set not provided (data).",
               "Отсутствует 2-й резалт-сет (данные)." ));
      }
      else
      {
         if ( ResultFile == null )
            throw new HAssertionFailureException();
         resultFile = ResultFile;
      }

      HConsole.PrintOperation(HLocal.TEXT(
         "Saving data to file: \"{0}\"",
         "Сохранение данных в файле: \"{0}\"" ),
         resultFile );

      writer = new StreamWriter( resultFile, false, ExportInUTF8 ?
         new UTF8Encoding( true ) : Encoding.Default );

      using ( new HWithCulture(null) )
      {
         if ( InsertColHeaders )
            writer.WriteLine( ComposeCSVHeaderRow( reader ) );
         int recNo = 0;
         while ( reader.Read() )
            writer.WriteLine( ComposeCSVDataRow( reader, ++recNo ) );
      }

      while ( reader.NextResult() ){}

      return;
   }
   catch (Exception e)
   {
      throw OpFailedExceptionCreator.Create( error = e );
   }
   finally
   {
      try
      {
         if ( writer != null )
            { writer.Close(); writer.Dispose(); }
      }
      catch (Exception e)
      {
         if ( error == null )
            throw OpFailedExceptionCreator.Create( error = e );
      }
      finally
      {
         try
         {
            if ( reader != null )
               { reader.Close(); reader.Dispose(); }
         }
         catch (Exception e)
         {
            if ( error == null )
               throw OpFailedExceptionCreator.Create( error = e );
         }
      }
   }
   throw new HDeadCodeBranchException();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // Program
//**************************************************************************************************

} // SqlToCsvExport
