using EasyDevCore.Database.EntityFrameworkCore;
using EasyDevCore.Common;
using Microsoft.EntityFrameworkCore.Storage;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using EasyDev.Database;

namespace EasyDevCore.Database.EntityFrameworkCore
{
    /// <summary>
    /// 
    /// </summary>
    public static class RelationalDataReaderExtensions
    {
        /// <summary>
        /// Gets the value.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="reader">The reader.</param>
        /// <param name="fieldName">Name of the field.</param>
        /// <param name="valueIfNull">The value if null.</param>
        /// <returns></returns>
        public static T GetValue<T>(this RelationalDataReader reader, string fieldName, T valueIfNull) => reader.DbDataReader.GetValue<T>(fieldName, valueIfNull);

        /// <summary>
        /// Gets the row.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <returns></returns>
        public static dynamic GetRow(this RelationalDataReader reader) => reader.DbDataReader.GetRow();


        /// <summary>
        /// Gets the row asynchronous.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public static Task<dynamic> GetRowAsync(this RelationalDataReader reader, CancellationToken cancellationToken)
            => reader.DbDataReader.GetRowAsync(cancellationToken);

        /// <summary>
        /// Fetches to dynamic.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <returns></returns>
        public static IList<dynamic> FetchToDynamic(this RelationalDataReader reader) => reader.DbDataReader.FetchToDynamic();

        /// <summary>
        /// Fetches to dynamic asynchronous.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public static Task<IList<dynamic>> FetchToDynamicAsync(this RelationalDataReader reader, CancellationToken cancellationToken = default)
            => reader.DbDataReader.FetchToDynamicAsync(cancellationToken);

        /// <summary>
        /// Fetches the fill list.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="reader">The reader.</param>
        /// <param name="list">The list.</param>
        /// <returns></returns>
        public static int FetchFillList<T>(this RelationalDataReader reader, IList<T> list) where T : class, new() => reader.DbDataReader.FetchFillList<T>(list);


        /// <summary>
        /// Fetches the fill list asynchronous.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="reader">The reader.</param>
        /// <param name="list">The list.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public static Task<int> FetchFillListAsync<T>(this RelationalDataReader reader, IList<T> list, CancellationToken cancellationToken = default)
            where T : class, new() => reader.DbDataReader.FetchFillListAsync(list, cancellationToken);

        /// <summary>
        /// Fetches to list.
        /// </summary>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <param name="reader">The reader.</param>
        /// <param name="selector">The selector.</param>
        /// <returns></returns>
        public static IList<TResult> FetchToList<TResult>(this RelationalDataReader reader, Func<dynamic, TResult> selector) => reader.DbDataReader.FetchToList(selector);

        /// <summary>
        /// Fetches to list asynchronous.
        /// </summary>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <param name="reader">The reader.</param>
        /// <param name="selector">The selector.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public static Task<IList<TResult>> FetchToListAsync<TResult>(this RelationalDataReader reader, Func<dynamic, TResult> selector, CancellationToken cancellationToken = default)
            => reader.DbDataReader.FetchToListAsync(selector, cancellationToken);

        /// <summary>
        /// Fetches to list.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="reader">The reader.</param>
        /// <param name="list">The list.</param>
        /// <returns></returns>
        public static IList<T> FetchToList<T>(this RelationalDataReader reader, IList<T> list = null) where T : class, new() => reader.DbDataReader.FetchToList(list);

        /// <summary>
        /// Fetches to list asynchronous.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="reader">The reader.</param>
        /// <param name="list">The list.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public static Task<IList<T>> FetchToListAsync<T>(this RelationalDataReader reader, IList<T> list = null, CancellationToken cancellationToken = default)
            where T : class, new() => reader.DbDataReader.FetchToListAsync(list, cancellationToken);

        /// <summary>
        /// Fetches the fill data set.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="dataSet">The data set.</param>
        public static int FetchFillDataSet(this RelationalDataReader reader, DataSet dataSet) => reader.DbDataReader.FetchFillDataSet(dataSet);

        /// <summary>
        /// Fetches the fill data set asynchronous.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="dataSet">The data set.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public static Task<int> FetchFillDataSetAsync(this RelationalDataReader reader, DataSet dataSet, CancellationToken cancellationToken = default)
            => reader.DbDataReader.FetchFillDataSetAsync(dataSet, cancellationToken);

        // <summary>
        /// <summary>
        /// Fetches to data set.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="dataSet">The data set.</param>
        /// <param name="parameters">The parameters.</param>
        /// <returns></returns>
        public static DataSet FetchToDataSet(this RelationalDataReader reader, DataSet dataSet = null, EasyDbParameterCollection parameters = null) => reader.DbDataReader.FetchToDataSet(dataSet, parameters);
        /// <summary>
        /// Fetches to data set asynchronous.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="DataSet">The entity set.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public static Task<DataSet> FetchToDataSetAsync(this RelationalDataReader reader, DataSet DataSet = null, CancellationToken cancellationToken = default)
            => reader.DbDataReader.FetchToDataSetAsync(DataSet, cancellationToken);

        /// <summary>
        /// Fetches to table.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="table">The table.</param>
        /// <returns></returns>
        public static int FetchFillTable(this RelationalDataReader reader, DataTable table) => reader.DbDataReader.FetchFillTable(table);

        /// <summary>
        /// Fetches to table.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="table">The table.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public static Task<int> FetchFillTableAsync(this RelationalDataReader reader, DataTable table, CancellationToken cancellationToken = default)
            => reader.DbDataReader.FetchFillTableAsync(table, cancellationToken);

        /// <summary>
        /// Fetches to table.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="table">The table.</param>
        /// <returns></returns>
        public static DataTable FetchToTable(this RelationalDataReader reader, DataTable table = null) => reader.DbDataReader.FetchToTable(table);


        /// <summary>
        /// Fetches to table asynchronous.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="table">The table.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public static Task<DataTable> FetchToTableAsync(this RelationalDataReader reader, DataTable table = null, CancellationToken cancellationToken = default)
            => reader.DbDataReader.FetchToTableAsync(table, cancellationToken);
    }
}
