using System;
using System.Collections;
using System.Data;
using System.Diagnostics;

namespace RStein.BusinessObjectBaseExamples
{
    /// <summary>
    /// Objednávka
    /// </summary>
    public class Order : BusinessObjectBase
    {
                    
        #region private variables
        private string m_description;
        private bool m_itemsLoaded = false;
        private Customer m_customer;
        private OrderItemCollection m_items = new OrderItemCollection(this);
        #endregion


        #region construction
        /// <summary>
        /// Kosntruktor
        /// </summary>
        /// <param name="description">Popisek zakázky</param>
        internal Order(string description, Customer customer) : base()
        {
            if ((description == null) ||
                (description == String.Empty))
            {
                throw new ArgumentException("description");
            }

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

            m_description = description;
            m_customer = customer;
            m_itemsLoaded = true;
                                      
    }

        /// <summary>
        /// Konstruktor
        /// </summary>
        /// <param name="id">Identifikátor objektu</param>
        internal Order(int id) : base (id)
        {
        
        }
        #endregion

                                            

        #region public properties
        
        
        /// <summary>
        /// Vrací popis objednávky
        /// </summary>
        public decimal Price
        {
            get
            {
                TriggerLoad();
                decimal currPrice;
                foreach (OrderItem item in Items)
                {
                    currPrice += item.Price;
                }    

                return currPrice;
            }
            
        }
        
        
        /// <summary>
        /// Vrací popis objednávky
        /// </summary>
        public string Description
        {
            get
            {
                TriggerLoad();
                return m_description;
            }
            set 
            {
                TriggerLoad();
                
                if (value == null)
                {
                    throw new ArgumentNullException();
                }

                CheckEquals(m_description, value);
                m_description = value;
            }
        }
        
        /// <summary>
        /// Vrací zákazníka objednávky
        /// </summary>
        public Customer Customer
        {
            get
            {
                TriggerLoad();
                return m_customer;
            }

            set
            {
                TriggerLoad();
                
                if (value == null)
                {
                    throw new ArgumentNullException();
                }
            
                CheckEquals(m_customer, value);
                m_customer = value;
            }
        }
        /// <summary>
        /// Vrací <see cref="OrderItemCollection"/> s položkami objednávky
        /// </summary>
        public OrderItemCollection Items
        {
            get
            {
                TriggerLoad();
                if (!m_itemsLoaded)
                {
                    loadItems();
                    m_itemsLoaded = true;
                }
                return m_items;
            }
        }
        #endregion

        
        #region Protected methods        
        ///<summary>
        /// Naplnění objektu z databáze
        ///</summary>
        protected override void DoInternalLoad()
        {
            
            DataTable sourceTable = DbComponent.Instance.Order_GetItem(m_id);

            Debug.Assert(sourceTable.Rows.Count == 1, "Invalid object data");
        
            if (sourceTable.Rows.Count != 1)
            {
                throw new ApplicationException("Invalid object data");
            }

            DoInternalLoad(sourceTable.Rows[0]);

        }
        
        /// <summary>
        /// Metoda nahraje objekt z předaného řádku
        /// </summary>
        /// <param name="row">Řádek se zdrojovými daty</param>        
        protected override void DoInternalLoad(DataRow row)
        {
                base.DoInternalLoad(row);
                
                m_description = (string)row["description"];
                m_customer = IdentityMap.Instance.Order((int) row["customerId"]);

        }

        ///<summary>
        /// Uložení objektu do databáze
        ///</summary>
        protected override void DoInternalSave()
        {
            DbComponent.Instance.Order_Update(
                                                  IsNew,
                                                  ref m_id,
                                                  Description,
                                                  Customer.Id,
                                                  (int) ObjectState
                                                );

            if (m_itemsLoaded)
            {
                SaveCollection(m_items);    
            }

        }

        
        #endregion Protected methods
        
        #region private methods
        /// <summary>
        /// Nahrání položek objednávky
        /// </summary>
        private void loadItems()
        {
            DataTable valuesTable = DbComponent.Instance.OrderItem_GetByOrderId(m_id);

            foreach(DataRow iterRow in valuesTable.Rows)
            {
                DataCacheHelper.Instance.StoreData(typeof(OrderItem), iterRow);
                int orderItemId = (int)iterRow["Id"];
                OrderItem item = IdentityMap.Instance.GetOrderItem(orderItemId);
                m_items.Add(item);
            }
        }
        #endregion private methods
    }
}