//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// DataHelpers.SQL satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
using System.Collections.Generic;
using System.Threading;
using System.Data;
using System.Data.SqlClient;
using u = user_rtx;

namespace DataHelpers.SQL {

/// <summary>
/// </summary>
partial class HQueryExecContextBase {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <exception cref="ArgumentException" />
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item> RSetToList<RSet_Item>( SqlDataReader dataReader,
                                                     bool closeReader = false )
where RSet_Item: new() =>
   RSetToListX<RSet_Item>( null, dataReader, closeReader );
/// <exception cref="ArgumentOutOfRangeException" />
/// <exception cref="ArgumentException" />
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item> RSetToList<RSet_Item>( [u.positive] int resultSetNo,
                                                     SqlDataReader dataReader,
                                                     bool closeReader = false )
where RSet_Item: new() =>
   RSetToListX<RSet_Item>( resultSetNo, dataReader, closeReader );
/// <exception cref="ArgumentOutOfRangeException" />
/// <exception cref="ArgumentException" />
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item> RSetToListX<RSet_Item>( [u.positive] int? resultSetNo,
                                                      SqlDataReader dataReader,
                                                      bool closeReader = false )
where RSet_Item: new()
{
   if ( resultSetNo.HasValue )
      u.arg_check.Positive( resultSetNo.Value, nameof(resultSetNo) );
   EnsureConnected();
   void disposeReader() {
      if ( closeReader ){
         dataReader.Close();
         dataReader.Dispose();
      }};
   List<RSet_Item> list;
   var curr = Current;
   curr._dataReader = dataReader;
   try {
      VerifyFieldCountX( resultSetNo, dataReader );
      list = new List<RSet_Item>();
      while ( dataReader.Read() )
         list.Add( new RSet_Item() );
   }
   catch {
      u.ops.Try( disposeReader );
      throw;
   }
   finally {
      curr._dataReader = null;
   }
   disposeReader();
   return list;
}

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

/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item>? RSetToListOrNull<RSet_Item>( SqlDataReader dataReader,
                                                            bool closeReader = false )
where RSet_Item: new()
{
   EnsureConnected();
   void disposeReader() {
      if ( closeReader ){
         dataReader.Close();
         dataReader.Dispose();
      }};
   List<RSet_Item>? list = null;
   var curr = Current;
   curr._dataReader = dataReader;
   try {
      if ( dataReader.FieldCount > 0 )
      {
         list = new List<RSet_Item>();
         while ( dataReader.Read() )
            list.Add( new RSet_Item() );
      }
   }
   catch {
      u.ops.Try( disposeReader );
      throw;
   }
   finally {
      curr._dataReader = null;
   }
   disposeReader();
   return list;
}

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

/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentException" />
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item>? NakedDoReaderCommand<RSet_Item>( [u.req] ref SqlCommand? command )
where RSet_Item: new() =>
   NakedDoReaderCommandX<RSet_Item>( null, ref command );

/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item>? NakedDoReaderCommand<RSet_Item>( string commandText )
where RSet_Item: new() =>
   NakedDoReaderCommandX<RSet_Item>( null, commandText );
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item>? NakedDoReaderCommand<RSet_Item>( string commandText,
                                                                params SqlParameter[] sqlParams )
where RSet_Item: new() =>
   NakedDoReaderCommandX<RSet_Item>( null, commandText, sqlParams );

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

/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item>? NakedDoReaderCommandFmt<RSet_Item>( string commandTextFmt,
                                                                   params object?[] args )
where RSet_Item: new() =>
   NakedDoReaderCommandFmtX<RSet_Item>( null, commandTextFmt, args );

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

/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentException" />
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item>? NakedDoReaderCommandX<RSet_Item>(
   Action? beforeScan, [u.req] ref SqlCommand? command )
where RSet_Item: new()
{
   u.arg_check.NN( command, nameof(command) );
   EnsureConnected();
   var rdr = HSqlCommandDispose.ExecuteReader( ref command );
   beforeScan?.Invoke();
   return RSetToListOrNull<RSet_Item>( rdr, true );
}

/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item>? NakedDoReaderCommandX<RSet_Item>(
   Action? beforeScan, string commandText )
where RSet_Item: new()
{
   EnsureConnected();
   var rdr = new HSqlOperator(Connection).ExecuteReader( OuterTransaction, commandText );
   beforeScan?.Invoke();
   return RSetToListOrNull<RSet_Item>( rdr, true );
}
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item>? NakedDoReaderCommandX<RSet_Item>(
   Action? beforeScan,
   string commandText, params SqlParameter[] sqlParams )
where RSet_Item: new()
{
   EnsureConnected();
   var rdr = new HSqlOperator(Connection).ExecuteReader( OuterTransaction, commandText, sqlParams );
   beforeScan?.Invoke();
   return RSetToListOrNull<RSet_Item>( rdr, true );
}

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

/// <exception cref="InvalidOperationException" />
[u.async_local]
public static List<RSet_Item>? NakedDoReaderCommandFmtX<RSet_Item>(
   Action? beforeScan,
   string commandTextFmt, params object?[] args )
where RSet_Item: new()
{
   EnsureConnected();
   var rdr = new HSqlOperator(Connection).ExecuteReaderFmt(
      OuterTransaction, commandTextFmt, args );
   beforeScan?.Invoke();
   return RSetToListOrNull<RSet_Item>( rdr, true );
}

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

/// <exception cref="ArgumentException" />
public static void VerifyFieldCount( SqlDataReader dataReader ) =>
   VerifyFieldCountX( null, dataReader );
/// <exception cref="ArgumentOutOfRangeException" />
/// <exception cref="ArgumentException" />
public static void VerifyFieldCount( [u.positive] int resultSetNo, SqlDataReader dataReader ) =>
   VerifyFieldCountX( resultSetNo, dataReader );
/// <exception cref="ArgumentOutOfRangeException" />
/// <exception cref="ArgumentException" />
public static void VerifyFieldCountX( [u.positive] int? resultSetNo, SqlDataReader dataReader )
{
   if ( resultSetNo.HasValue )
      u.arg_check.Positive( resultSetNo.Value, nameof(resultSetNo) );
   if ( dataReader.FieldCount <= 0 )
      if ( resultSetNo > 0 )
         throw new ArgumentException(AppendProcNameToMessage(u.local.T(
            $"Result-set is not found or is invalid (#{resultSetNo}).",
            $"Резалт-сет не обнаружен либо является недействительным (#{resultSetNo})." )));
      else
         throw new ArgumentException(AppendProcNameToMessage(u.local.T(
            "Result-set is not found or is invalid.",
            "Резалт-сет не обнаружен либо является недействительным." )));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HQueryExecContextBase

} // DataHelpers.SQL
