using System;
using System.Collections;
using System.Data;
using System.Threading;


    /// <summary>
    /// Pomocná třída pro uchování záznamů z databáze (Pseudo singleton)
    /// </summary>
    /// <remarks>Metoda je používána hlavně pro nahrání objektů v kolekci</remarks>
    public class DataCacheHelper
    {
        #region private static variables
        private static Hashtable _instances;
        #endregion private static variables
        
        #region private variables
        private Hashtable typesDataMap;
        #endregion private variables
        
        
        #region Constructors
        /// <summary>
        /// privátní konstruktor
        /// </summary>
        private DataCacheHelper() : base()
        {
            typesDataMap = new Hashtable();            
        }

        /// <summary>
        /// Statický konstruktor
        /// </summary>
        static DataCacheHelper()
        {
            _instances = new Hashtable();
        }
        #endregion Constructors

        #region public static methods
        /// <summary>
        /// Metoda odebere instanci pro aktuální thread
        /// </summary>
        public static void CloseInstance()
        {
            Hashtable instances = Hashtable.Synchronized(_instances);
            
            DataCacheHelper inst = (DataCacheHelper)instances[Thread.CurrentThread] as DataCacheHelper;
            
            if(inst != null)
            {
                _instances.Remove(Thread.CurrentThread);
            }
        }

        #endregion
        
        #region public static properties
        /// <summary>
        /// Globální přístupový bod k jediné instanci třídy DataCacheHelper
        /// </summary>
        public static DataCacheHelper Instance
        {
            get
            {
                Hashtable instances = Hashtable.Synchronized(_instances);

                DataCacheHelper helper = instances[Thread.CurrentThread]  as DataCacheHelper;

            
                if(helper == null)
                {
                    helper = new DataCacheHelper();
                    instances.Add(Thread.CurrentThread, helper);
                }

                return helper;


            }
        }

        #endregion public static properties

        #region public methods

        /// <summary>
        /// Uložení řádku
        /// </summary>
        /// <param name="type">Typ, pro který jsou data uchovávána</param>
        /// <param name="row">Datový řádek, který má být uložen</param>
        /// <remarks>Metoda předpokládá, že row obsahuje sloupec Id.Jestliže sloupec Id není nalezen, je vyvolána výjimka <see cref="ArgumentException" /></remarks>
        public void StoreData(Type type, DataRow row)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (row == null)
            {
                throw new ArgumentNullException("row");                
            }

            if (!row.Table.Columns.Contains("Id"))
            {
                throw new ArgumentException("DataRow does not belong to the table with column Id","row");
            }
            
            int rowId = (int )row["id"];
            Hashtable rowHashTable = typesDataMap[type] as Hashtable;

            if (rowHashTable == null)
            {
                rowHashTable = new Hashtable();
                typesDataMap.Add(type,rowHashTable);                
            }
            
            if (rowHashTable.ContainsKey(rowId))
            {
                rowHashTable.Remove(rowId);
            }
            
            rowHashTable.Add(rowId, row);
        }


        /// <summary>
        /// Metoda vrátí dříve uložená data objektu
        /// </summary>
        /// <param name="type">Typ objektu, jehož data mají bý vyzvednuta</param>
        /// <param name="businessObjectId">Id objektu, jehož data mají být vyzvednuta</param>
        /// <returns><see cref="DataRow"> s daty objektu, jestliže byla dříve uložen, jinak null</see></returns>
        /// <remarks>Po vrácení jsou data z objektu <see cref="DataCacheHelper"/> odstraněna</remarks>
        public DataRow GetData(Type type, int businessObjectId)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            Hashtable rowHashTable = typesDataMap[type] as Hashtable;

            if (rowHashTable == null)
            {
                return null;
            }
            
            DataRow row = rowHashTable[businessObjectId] as DataRow;

            if (row != null)
            {
                rowHashTable.Remove(row);
            }
            
            return (row);
        }
        #endregion public methods


    }