using System;
using System.Data;
using System.Diagnostics.CodeAnalysis;
using SDA.DataProvider.Core;

namespace SDA.DataProvider
{
    /// <summary>
    /// Adatbázis lekérdezések eredményhalmazának felolvasását végző osztály.
    /// </summary>
    public class SDADataReader : IDisposable
    {
        internal SDADataReaderWrapper Reader;

        internal SDADataReader()
        {
        }

        internal SDADataReader(SDADataReaderWrapper reader)
        {
            Reader = reader;
        }

        bool _disposed;

        /// <summary>
        /// Explicit destruktor.
        /// </summary>
        /// <param name="disposing">Programozott felszabadítás?</param>
        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
            {
                return;
            }
            if (disposing)
            {
                if (Reader != null)
                {
                    Reader.Dispose();
                    Reader = null;
                }
            }
            _disposed = true;
        }

        /// <summary>
        /// Eldobja az objektumot.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Lezárja az objektumot.
        /// </summary>
        public void Close()
        {
            Reader.Close();
        }

        /// <summary>
        /// A következő rekordra áll.
        /// </summary>
        /// <returns></returns>
        public bool Read()
        {
            return Reader.Read();
        }

        /// <summary>
        /// A következő eredményre áll.
        /// </summary>
        /// <returns>True, ha van még eredmény; egyébként False.</returns>
        public bool NextResult()
        {
            return Reader.NextResult();
        }

        /// <summary>
        /// Megvizsgálja, hogy a jelenlegi rekord adott oszlopának van-e értéke.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>True, ha nincs értéke; egyébként False</returns>
        public bool IsDBNull(int index)
        {
            return Reader.IsDBNull(index);
        }

        /// <summary>
        /// A megadott oszlop értékét logikai típusként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public bool GetBoolean(int index)
        {
            return Reader.GetBoolean(index);
        }

        /// <summary>
        /// A megadott oszlop értékét bájtként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public byte GetByte(int index)
        {
            return Reader.GetByte(index);
        }

        /// <summary>
        /// A megadott oszlop értékét karakterként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public char GetChar(int index)
        {
            return Reader.GetChar(index);
        }

        /// <summary>
        /// A megadott oszlop értékét dátum-időként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public DateTime GetDateTime(int index)
        {
            return Reader.GetDateTime(index);
        }

        /// <summary>
        /// A megadott oszlop értékét számként (decimal) adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public decimal GetDecimal(int index)
        {
            return Reader.GetDecimal(index);
        }

        /// <summary>
        /// A megadott oszlop értékét lebegőpontos típusként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public double GetDouble(int index)
        {
            return Reader.GetDouble(index);
        }

        /// <summary>
        /// A megadott oszlop értékét 16 bites előjeles egész típusként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public short GetInt16(int index)
        {
            return Reader.GetInt16(index);
        }

        /// <summary>
        /// A megadott oszlop értékét 32 bites egész típusként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public int GetInt32(int index)
        {
            return Reader.GetInt32(index);
        }

        /// <summary>
        /// A megadott oszlop értékét 64 bites egész típusként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public long GetInt64(int index)
        {
            return Reader.GetInt64(index);
        }

        /// <summary>
        /// A megadott oszlop értékét karakterláncként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public string GetString(int index)
        {
            return Reader.GetString(index);
        }

        /// <summary>
        /// A megadott oszlop értékét karakterláncként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public string GetLongString(int index)
        {
            return Reader.GetLongString(index);
        }

        /// <summary>
        /// A megadott oszlop értékét objektumként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop értéke</returns>
        public object GetValue(int index)
        {
            return Reader.GetValue(index);
        }

        /// <summary>
        /// A megadott oszlop Guid értékét adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <returns>Az oszlop Guid értéke</returns>
        public Guid GetGuid(int index)
        {
            return Reader.GetGuid(index);
        }

        /// <summary>
        /// Visszaadja a jelenlegi rekord összes oszlopának értékét.
        /// </summary>
        /// <param name="values">Objektumtömb, amibe az értékeket kell másolni</param>
        /// <returns>Tömbbe másolt objektumok száma</returns>
        public int GetValues(object[] values)
        {
            return Reader.GetValues(values);
        }

        /// <summary>
        /// Visszaadja az objektum metaadatait.
        /// </summary>
        /// <returns>Egy DataTable objektum, ami az oszlopok leírását tartalmazza</returns>
        [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public DataTable GetSchemaTable()
        {
            return Reader.GetSchemaTable();
        }

        /// <summary>
        /// Visszaadja a megadott nevű oszlop értékét.
        /// </summary>
        public object this[string name] => Reader[name];

        /// <summary>
        /// Visszaadja a megadott indexű oszlop értékét.
        /// </summary>
        public object this[int index]
        {
            get
            {
                return Reader[index];
            }
        }

        /// <summary>
        /// Lezárult-e az olvasás?
        /// </summary>
        public bool IsClosed
        {
            get
            {
                return Reader.IsClosed;
            }
        }

        /// <summary>
        /// Az aktuális sor oszlopainak száma.
        /// </summary>
        public int FieldCount
        {
            get
            {
                return Reader.FieldCount;
            }
        }

        /// <summary>
        /// Megadja egy mező indexét.
        /// </summary>
        /// <param name="fieldName">A kért mező neve</param>
        /// <returns>Az oszlop indexe</returns>
        public int GetOrdinal(string fieldName)
        {
            return Reader.GetOrdinal(fieldName);
        }

        #region Nem szabványos kényelmi funkciók

        /// <summary>
        /// A megadott oszlop értékét logikai típusként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <param name="defaultValue">Null esetén mivel térjen vissza.</param>
        /// <returns>Az oszlop értéke</returns>
        public bool? GetBoolean(int index, bool? defaultValue)
        {
            return IsDBNull(index) ? defaultValue : Reader.GetBoolean(index);
        }

        /// <summary>
        /// A megadott oszlop értékét bájtként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <param name="defaultValue">Null esetén mivel térjen vissza.</param>
        /// <returns>Az oszlop értéke</returns>
        public byte? GetByte(int index, byte? defaultValue)
        {
            return IsDBNull(index) ? defaultValue : Reader.GetByte(index);
        }

        /// <summary>
        /// A megadott oszlop értékét karakterként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <param name="defaultValue">Null esetén mivel térjen vissza.</param>
        /// <returns>Az oszlop értéke</returns>
        public char? GetChar(int index, char? defaultValue)
        {
            return IsDBNull(index) ? defaultValue : Reader.GetChar(index);
        }

        /// <summary>
        /// A megadott oszlop értékét dátum-időként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <param name="defaultValue">Null esetén mivel térjen vissza.</param>
        /// <returns>Az oszlop értéke</returns>
        public DateTime? GetDateTime(int index, DateTime? defaultValue)
        {
            return IsDBNull(index) ? defaultValue : Reader.GetDateTime(index);
        }

        /// <summary>
        /// A megadott oszlop értékét számként (decimal) adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <param name="defaultValue">Null esetén mivel térjen vissza.</param>
        /// <returns>Az oszlop értéke</returns>
        public decimal? GetDecimal(int index, decimal? defaultValue)
        {
            return IsDBNull(index) ? defaultValue : Reader.GetDecimal(index);
        }

        /// <summary>
        /// A megadott oszlop értékét lebegőpontos típusként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <param name="defaultValue">Null esetén mivel térjen vissza.</param>
        /// <returns>Az oszlop értéke</returns>
        public double? GetDouble(int index, double? defaultValue)
        {
            return IsDBNull(index) ? defaultValue : Reader.GetDouble(index);
        }

        /// <summary>
        /// A megadott oszlop értékét 16 bites előjeles egész típusként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <param name="defaultValue">Null esetén mivel térjen vissza.</param>
        /// <returns>Az oszlop értéke</returns>
        public short? GetInt16(int index, short? defaultValue)
        {
            return IsDBNull(index) ? defaultValue : Reader.GetInt16(index);
        }

        /// <summary>
        /// A megadott oszlop értékét 32 bites egész típusként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <param name="defaultValue">Null esetén mivel térjen vissza.</param>
        /// <returns>Az oszlop értéke</returns>
        public int? GetInt32(int index, int? defaultValue)
        {
            return IsDBNull(index) ? defaultValue : Reader.GetInt32(index);
        }

        /// <summary>
        /// A megadott oszlop értékét 64 bites egész típusként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <param name="defaultValue">Null esetén mivel térjen vissza.</param>
        /// <returns>Az oszlop értéke</returns>
        public long? GetInt64(int index, long? defaultValue)
        {
            return IsDBNull(index) ? defaultValue : Reader.GetInt64(index);
        }

        /// <summary>
        /// A megadott oszlop értékét karakterláncként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <param name="defaultValue">Null esetén mivel térjen vissza.</param>
        /// <returns>Az oszlop értéke</returns>
        public string GetString(int index, string defaultValue)
        {
            return IsDBNull(index) ? defaultValue : Reader.GetString(index);
        }

        /// <summary>
        /// A megadott oszlop értékét objektumként adja vissza.
        /// </summary>
        /// <param name="index">Az oszlop sorszáma</param>
        /// <param name="defaultValue">Null esetén mivel térjen vissza.</param>
        /// <returns>Az oszlop értéke</returns>
        public object GetValue(int index, object defaultValue)
        {
            return IsDBNull(index) ? defaultValue : Reader.GetValue(index);
        }

        #endregion
    }
}