using CareFusion.Lib.StorageSystem;
using CareFusion.Lib.StorageSystem.Input;
using System;
using System.Collections.Generic;
using System.Data;

namespace CareFusion.ITSystemSimulator
{
    /// <summary>
    /// Class which contains the data model of the stock deliveries.
    /// </summary>
    public class StockDeliveryModel
    {
        #region Members

        /// <summary>
        /// Stock delivery item data model.
        /// </summary>
        private DataTable _stockDeliveryItemModel = new DataTable();

        #endregion

        #region Properties

        /// <summary>
        /// Gets stock delivery data item model.
        /// </summary>
        public DataTable StockDeliveryItems
        {
            get { return _stockDeliveryItemModel; }
        }

        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="StockDeliveryModel"/> class.
        /// </summary>
        public StockDeliveryModel()
        {
            DataColumn column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(string);
            column.ColumnName = "Delivery";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(string);
            column.ColumnName = "ArticleID";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(string);
            column.ColumnName = "ProductCode";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(string);
            column.ColumnName = "Name";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(string);
            column.ColumnName = "Dosage";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(string);
            column.ColumnName = "Packaging";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(bool);
            column.ColumnName = "Fridge";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(uint);
            column.ColumnName = "MaxSubItems";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(string);
            column.ColumnName = "Batch";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(string);
            column.ColumnName = "ExternalID";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(DateTime);
            column.ColumnName = "ExpiryDate";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(uint);
            column.ColumnName = "PackCount";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(string);
            column.ColumnName = "StockLocation";

            column = _stockDeliveryItemModel.Columns.Add();
            column.DataType = typeof(string);
            column.ColumnName = "MachineLocation";

        }

        /// <summary>
        /// Sends the current stock delivery set to the specified storage system.
        /// </summary>
        /// <param name="storageSystem">Storage system to send the stock deliveries too.</param>
        public void Send(IStorageSystem storageSystem)
        {
            var deliveryMap = new Dictionary<string, List<DataRow>>();
            var deliveryList = new List<IStockDelivery>();

            foreach (DataRow row in _stockDeliveryItemModel.Rows)
            {
                var deliveryNumber = (row[0] != DBNull.Value) ? ((string)row[0]).Trim() : string.Empty;

                if (deliveryMap.ContainsKey(deliveryNumber) == false)
                {
                    deliveryMap.Add(deliveryNumber, new List<DataRow>());
                }

                deliveryMap[deliveryNumber].Add(row);
            }

            foreach (string deliveryNumber in deliveryMap.Keys)
            {
                var delivery = storageSystem.CreateStockDelivery(deliveryNumber);

                foreach (var itemRow in deliveryMap[deliveryNumber])
                {
                    delivery.AddItem(
                    GetValue(itemRow, "ArticleID", string.Empty),
                    GetValue(itemRow, "ProductCode", string.Empty),
                    GetValue(itemRow, "Name", string.Empty),
                    GetValue(itemRow, "Packaging", string.Empty),
                    GetValue(itemRow, "Dosage", string.Empty),
                    GetValue(itemRow, "Fridge", false),
                    GetValue(itemRow, "MaxSubItems", (uint)0),
                    GetValue(itemRow, "Batch", string.Empty),
                    GetValue(itemRow, "ExternalID", string.Empty),
                    GetValue<DateTime?>(itemRow, "ExpiryDate", null),
                    GetValue(itemRow, "PackCount", (uint)0),
                    GetValue(itemRow, "StockLocation", string.Empty),
                    GetValue(itemRow, "MachineLocation", string.Empty));
                }

                deliveryList.Add(delivery);
            }

            storageSystem.AddStockDeliveries(deliveryList);
        }

        private T GetValue<T>(DataRow row, string columnName, T defaultvalue)
        {
            return row[columnName] != DBNull.Value ? (T)row[columnName] : defaultvalue;
        }
    }
}
