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

namespace DataHelpers.SQL {

static partial class HDB {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <exception cref="InvalidCastException" />
/// <exception cref="HDatabaseException" />
[u.opt_result]
public static T GetFieldValue<T>( string? procedureName,
                                  SqlDataReader dataReader, string fieldName,
                                  IDictionary<string,int>? fieldIndexer,
                                  bool treatNullAsDefaultValue = false )
{
   int fieldIdx = GetFieldIndex( procedureName, dataReader, fieldName, fieldIndexer, true );
   object value = dataReader[ fieldIdx ];
   var type = typeof(T);
   if (!( value is DBNull ))
      try { return (T)value; }
      catch ( Exception e ) {
         throw new InvalidCastException(u.local.F(
            "Can not cast value of result-set field “{0}” to type “{1}”.{2}\n"+
            "{3}",
            "Не удаётся привести значение поля резалт-сета “{0}” к типу “{1}”.{2}\n"+
            "{3}",
            fieldName, type, LFnStoredProcOrEmpty( procedureName ), e.Message ));
      }
   if ( treatNullAsDefaultValue || u.type.IsNullable( type ) )
      return default!;
   throw new InvalidCastException(u.local.F(
      "Result-set field “{0}” of type “{1}” has null value.{2}",
      "Поле резалт-сета “{0}” типа “{1}” содержит нул-значение.{2}",
      fieldName, type, LFnStoredProcOrEmpty( procedureName ) ));
}

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

/// <exception cref="ArgumentException" />
/// <exception cref="InvalidCastException" />
/// <exception cref="HDatabaseException" />
[u.opt_result]
public static T GetOutputParameterValue<T>( string procedureName,
                                            SqlParameter parameter,
                                            bool treatNullAsDefaultValue = false )
{
   string paramName = parameter.ParameterName;
   if ( !u.ops.IsOneOf( parameter.Direction,
                        ParameterDirection.Output,
                        ParameterDirection.InputOutput ) )
      throw u.e_argument.New(u.local.T(
         "Parameter “{0}” is not output or input-output parameter.{1}",
         "Параметр “{0}” не является выходным либо входным-выходным параметром.{1}"
      ), paramName, LFnStoredProcOrEmpty( procedureName ));
   object value = parameter.Value;
   var type = typeof(T);
   if (!( value is DBNull ))
      try { return (T)value; }
      catch ( Exception e ) {
         throw new InvalidCastException(u.local.F(
            "Can not cast value of “{0}”-parameter to type “{1}”.{2}\n"+
            "{3}",
            "Не удаётся привести значение параметра “{0}” к типу “{1}”.{2}\n"+
            "{3}",
            paramName, type, LFnStoredProcOrEmpty( procedureName ), e.Message ));
      }
   if ( treatNullAsDefaultValue || u.type.IsNullable( type ) )
      return default!;
   throw new InvalidCastException(u.local.F(
      "Output parameter “{0}” of type “{1}” has null value.{2}",
      "Выходной параметр “{0}” типа “{1}” содержит нул-значение.{2}",
      paramName, type, LFnStoredProcOrEmpty( procedureName ) ));
}

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

/// <exception cref="InvalidCastException" />
[u.opt_result]
public static T GetSPReturnValue<T>( string procedureName, SqlParameter returnValueParam )
{
   var rv = returnValueParam.Value;
   if ( rv == null )
      return default!;
   try { return (T)rv; }
   catch ( Exception e ) {
      throw new InvalidCastException(u.local.F(
         "Can not cast return value stored procedure [{0}] to type “{1}”.\n"+
         "{2}",
         "Не удаётся привести возвратное значение хранимой процедуры [{0}] к типу “{1}”.\n"+
         "{2}",
         procedureName, typeof(T), e.Message ));
   }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HDB

} // DataHelpers.SQL
