using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Globalization;
using System.Windows;
using System.Reflection;

namespace SCAN
{
    public partial class Form_Outbound : Form
    {
        private lib.LogWriter logger = lib.LogWriter.getInstance();

        private DateTime outboundDate;
        private string customerId;
        private List<OutboundItemScheduleDisplay> outboundScheduleItems;
        private int currentItem; // zero base item index

        public static Form_Outbound _Form_Instance;
        public static List<lib.db.HT_OB> outboundItems;
        List<OutboundItemDisplay> items;

        bool isFull = true;
        bool isModified = false;

        // Master table
        private Dictionary<string, int> __PackageTypes = lib.db.PackageType.getBoxSizeList();
        private Dictionary<string, lib.db.Item> __ItemList = lib.db.Item.getItemList();

        public Form_Outbound(DateTime outboundDate, string customerId, List<OutboundItemScheduleDisplay> list, int index)
        {
            InitializeComponent();

            this.outboundDate = outboundDate;
            this.customerId = customerId;
            this.outboundScheduleItems = list;
            this.currentItem = index;

            

        }

        private void Form_Load(object sender, EventArgs e)
        {
            // set screen resolution
            if (System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width == 240)
            {
                resolution.ScreenSize.VGAtoQVGA(this);
            }

            // disable maximize and minimize button
            this.MaximizeBox = !this.MaximizeBox;
            this.MinimizeBox = !this.MinimizeBox;

            // set form instance
            _Form_Instance = this;

            // data grid
            InitialDataGrid(); 

            // initiate data
            lbUser.Text = Form_Login._Form_LoginInstance.userName;
            lblPage.Text = String.Format("{0}/{1}", currentItem + 1, outboundScheduleItems.Count);
            form_Reset();
        }

        /*
        void btScanLib_OnScan(string result)
        {

            double t_pkg_qty_plan = 0;
            double t_pkg_qty_act = 0;
            double t_qty_plan = 0;
            double t_qty_act = 0;
            string item_id = result;

            // verify scan item id match with current item_id
            if (!item_id.Equals(lblPartsNo.Text))
            {
                Form frm = new Form_Msg("Parts not match!", Color.Red);
                frm.ShowDialog();
                return;
            }

            if (isFull)
            {
                Form frm = new Form_Msg("No picking for this parts!", Color.Red);
                frm.ShowDialog();
                return;
            }

            // update quantity to list
            for (int i = 0; i < outboundItems.Count; i++)
            {
                lib.db.HT_OB ob = outboundItems.ElementAt(i);
                int box_plan = int.Parse(ob.__COLUMNS["pkg_qty_plan"]);
                int box_act = int.Parse(ob.__COLUMNS["pkg_qty_act"].Equals(String.Empty) ? "0" : ob.__COLUMNS["pkg_qty_act"]);
                if (box_plan > box_act)
                {
                    box_act++;
                    Dictionary<string, string> cols = new Dictionary<string, string>(ob.__COLUMNS);
                    cols["pkg_qty_act"] = box_act.ToString();
                    cols["pc_qty_act"] = (box_act * __PackageTypes[item_id]).ToString();
                    outboundItems[i] = new SCAN.lib.db.HT_OB(cols.Values.ToArray<string>());
                    isModified = true;

                    // check is the last slot
                    if (box_plan == box_act && i == outboundItems.Count - 1)
                    {
                        isFull = true;
                    }
                    break;
                }
            }

            // update datagrid view
            items = OutboundItemDisplay.LoadCollectionData(outboundItems);


            // Add total row
            foreach (lib.db.HT_OB ob in outboundItems)
            {
                t_pkg_qty_plan += double.Parse(ob.__COLUMNS["pkg_qty_plan"]);
                t_qty_plan += double.Parse(ob.__COLUMNS["pc_qty_plan"]);
                t_pkg_qty_act += double.Parse(ob.__COLUMNS["pkg_qty_act"]);
                t_qty_act += double.Parse(ob.__COLUMNS["pc_qty_act"]);
            }
            items.Add(new OutboundItemDisplay());
            items.Add(new OutboundItemDisplay());
            items.Add(new OutboundItemDisplay()
            {
                Location_id = "Total",
                Pkg_qty_plan = String.Format("{0:0.##}", t_pkg_qty_plan),
                Pkg_qty_act = String.Format("{0:0.##}", t_pkg_qty_act),
                Qty_plan = String.Format("{0:0.##}", (int)Math.Ceiling(t_qty_plan)),
                Qty_act = String.Format("{0:0.##}", (int)Math.Ceiling(t_qty_act))
            });

            var blist = new BindingList<OutboundItemDisplay>(items);
            dataGrid.DataSource = blist;
        }
         * */

        private void btnBack_Click(object sender, EventArgs e)
        {
            if (isModified)
            {
                DialogResult ret = MessageBox.Show("Are you sure to exit page? The unsave data will be lost."
                    , "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2);
                if (ret == DialogResult.No)
                    return;
            }

            Form_OutboundSchedule._Form_Instance.Show();
            this.Close();
        }

        private void form_Reset()
        {
            lblPartsNo.Text = outboundScheduleItems.ElementAt(currentItem).Item_id;

            queryRecord();

            btnConfirm.Enabled = false;
            if (!outboundScheduleItems.ElementAt(currentItem).Status.Equals("Complete"))
            {
                isFull = false;
                btnConfirm.Enabled = true;
            }

            btnPrev.Enabled = false;
            btnNext.Enabled = false;
            if (currentItem < outboundScheduleItems.Count - 1)
            {
                btnNext.Enabled = true;
            }
            if (currentItem > 0)
            {
                btnPrev.Enabled = true;
            }
        }

        private void InitialDataGrid()
        {
            int grid_width = 475;
            // hidden column and row header
            dataGrid.ColumnHeadersVisible = true;
            dataGrid.RowHeadersVisible = false;
            dataGrid.Click += new EventHandler(dataGrid_Click);

            // set Row header height
            foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(dataGrid))
            {
                string name = descriptor.Name;
                object value = descriptor.GetValue(dataGrid);
                logger.Log(String.Format("{0}={1}", name, value));
            }
            FieldInfo[] fields = typeof(DataGrid).GetFields(
                         BindingFlags.NonPublic |
                         BindingFlags.Instance);
            foreach (FieldInfo info in fields)
            {
                logger.Log(String.Format("{0}", info.Name));
            }
            //var p = typeof(DataGrid).GetField("headerFontHeight",
            //    System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            //p.SetValue(dataGrid, 20 * 2);

            //var m = typeof(DataGrid).GetMethod("OnLayout",
            //    System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            //m.Invoke(dataGrid, new object[] { null });
            //dataGrid.Invalidate();

            // set style
            DataGridTableStyle tableStyle = new DataGridTableStyle();
            tableStyle.MappingName = (new BindingList<OutboundItemDisplay>()).GetType().Name;

            // Column 1
            DataGridTextBoxColumn tbc1 = new DataGridTextBoxColumn();
            tbc1.Width = grid_width * 7 / 100 ;
            tbc1.MappingName = "No";
            tbc1.HeaderText = "#";
            tableStyle.GridColumnStyles.Add(tbc1);

            // Column 2
            DataGridTextBoxColumn tbc2 = new DataGridTextBoxColumn();
            tbc2.Width = grid_width * 20 / 100;
            tbc2.MappingName = "Product_date";
            tbc2.HeaderText = "P/D date";
            tableStyle.GridColumnStyles.Add(tbc2);

            // Column 3
            DataGridTextBoxColumn tbc3 = new DataGridTextBoxColumn();
            tbc3.Width = grid_width * 20 / 100;
            tbc3.MappingName = "Location_id";
            tbc3.HeaderText = "Location";
            tableStyle.GridColumnStyles.Add(tbc3);

            // Column 4
            DataGridTextBoxColumn tbc4 = new DataGridTextBoxColumn();
            tbc4.Width = grid_width * 12 / 100;
            tbc4.MappingName = "Pkg_qty_plan";
            tbc4.HeaderText = "B/Plan";
            tableStyle.GridColumnStyles.Add(tbc4);

            /*
            DataGridTextBoxColumnStyle tbc4 = new DataGridTextBoxColumnStyle() 
            {
                Width = grid_width * 10 / 100,
                MappingName = "Pkg_qty_plan",
                HeaderText = "Box Plan",
            };
            //tbc4.OnPaint += new PaintEventHandler(tbcStatus_OnPaint1);
            tableStyle.GridColumnStyles.Add(tbc4);
             * */

            // Column 5
            DataGridTextBoxColumn tbc5 = new DataGridTextBoxColumn();
            tbc5.Width = grid_width * 11 / 100;
            tbc5.MappingName = "Pkg_qty_act";
            tbc5.HeaderText = "B/Act";
            tableStyle.GridColumnStyles.Add(tbc5);

            // Column 6
            DataGridTextBoxColumn tbc6 = new DataGridTextBoxColumn();
            tbc6.Width = grid_width * 15 / 100;
            tbc6.MappingName = "Qty_plan";
            tbc6.HeaderText = "ps/Plan";
            tableStyle.GridColumnStyles.Add(tbc6);

            // Column 7
            DataGridTextBoxColumn tbc7 = new DataGridTextBoxColumn();
            tbc7.Width = grid_width * 13 / 100;
            tbc7.MappingName = "Qty_act";
            tbc7.HeaderText = "ps/Act";
            tableStyle.GridColumnStyles.Add(tbc7);

            dataGrid.TableStyles.Clear();
            dataGrid.TableStyles.Add(tableStyle);
        }

        void dataGrid_Click(object sender, EventArgs e)
        {
            try
            {
                if (outboundItems.Count() == 0) return;

                int row = dataGrid.CurrentCell.RowNumber;

                Form frm = new Form_OutboundDetail(outboundItems, row);
                frm.Show();
                this.Hide();
            }
            catch (ArgumentOutOfRangeException ex)
            {
            }
        }

        void tbcStatus_OnPaint1(Graphics g, Rectangle Bounds, CurrencyManager Source, int RowNum, Brush BackBrush, Brush ForeBrush, bool AlignToRight)
        {

            string value = RowNum < outboundItems.Count ? items[RowNum].Pkg_qty_plan : "";

            ForeBrush = new SolidBrush(Color.Black);

            BackBrush = new SolidBrush(Color.LightGray);

            g.FillRectangle(BackBrush, Bounds.X, Bounds.Y, Bounds.Width, Bounds.Height);

            System.Drawing.Font font = new Font(System.Drawing.FontFamily.GenericSansSerif,
                (float)14, FontStyle.Bold);
            SizeF size = g.MeasureString(value, font);
            g.DrawString(value, font, ForeBrush,
                Bounds.X + (Bounds.Width - size.Width) / 2, Bounds.Y + ((Bounds.Height - font.Size) / 2));
        }

        /*

        void tbcStatus_OnPaint(Graphics g, Rectangle Bounds, CurrencyManager Source, int RowNum, Brush BackBrush, Brush ForeBrush, bool AlignToRight)
        {

            string value = items[RowNum].Status;

            ForeBrush = new SolidBrush(Color.White);

            if (value.ToLower().Equals("ok"))
            {
                BackBrush = new SolidBrush(Color.LimeGreen);
            }
            else if (value.ToLower().Equals("ng"))
            {
                BackBrush = new SolidBrush(Color.Red);
            }
            else if (value.ToLower().Equals("working"))
            {
                BackBrush = new SolidBrush(Color.Blue);
            }
            else
            {
                BackBrush = new SolidBrush(Color.DarkGray);
            }

            g.FillRectangle(BackBrush, Bounds.X, Bounds.Y, Bounds.Width, Bounds.Height);

            System.Drawing.Font font = new Font(System.Drawing.FontFamily.GenericSansSerif,
                (float)12.25, FontStyle.Regular);
            SizeF size = g.MeasureString(value, font);
            g.DrawString(value, font, ForeBrush,
                Bounds.X + (Bounds.Width - size.Width) / 2, Bounds.Y + ((Bounds.Height - font.Size) / 2));
        }
         * */

        /////////////////////////////////////////////////////////////
        /// Query
        /////////////////////////////////////////////////////////////
        private void queryRecord()
        {
            outboundItems = new List<lib.db.HT_OB>();

            OutboundItemScheduleDisplay schedule = outboundScheduleItems.ElementAt(currentItem);

            double t_pkg_qty_plan = 0;
            double t_pkg_qty_act = 0;
            double t_qty_plan = 0;
            double t_qty_act = 0;

            List<string[]> rows = (new lib.db.HT_OB()).get(
                (new lib.db.HT_OB()).__COLUMNS
                , String.Format("outbound_date='{0}' AND customer_id='{1}' AND item_id='{2}'"
                    ,outboundDate.ToString("yyyyMMdd"), customerId, schedule.Item_id)
                , null, null, null);
            foreach (string[] row in rows)
            {
                logger.Log(row);
                outboundItems.Add(new lib.db.HT_OB(row));
            }

            items = OutboundItemDisplay.LoadCollectionData(outboundItems);

            // Add total row
            foreach (lib.db.HT_OB ob in outboundItems)
            {
                t_pkg_qty_plan += double.Parse(ob.__COLUMNS["pkg_qty_plan"]);
                t_qty_plan += double.Parse(ob.__COLUMNS["pc_qty_plan"]);
                t_pkg_qty_act += double.Parse(ob.__COLUMNS["pkg_qty_act"]);
                t_qty_act += double.Parse(ob.__COLUMNS["pc_qty_act"]);
            }
            items.Add(new OutboundItemDisplay());
            items.Add(new OutboundItemDisplay());
            items.Add(new OutboundItemDisplay() {
                Location_id = "Total",
                Pkg_qty_plan = String.Format("{0:0.##}", t_pkg_qty_plan),
                Pkg_qty_act = String.Format("{0:0.##}", t_pkg_qty_act),
                Qty_plan = String.Format("{0:0.##}", (int)Math.Ceiling(t_qty_plan)),
                Qty_act = String.Format("{0:0.##}", (int)Math.Ceiling(t_qty_act))
            });

            var blist = new BindingList<OutboundItemDisplay>(items);
            dataGrid.DataSource = blist;
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            if (isModified)
            {
                DialogResult ret = MessageBox.Show("Are you sure to go next page? The unsave data will be lost."
                    , "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2);
                if (ret == DialogResult.No)
                    return;
            }

            currentItem++;
            lblPage.Text = String.Format("{0}/{1}", currentItem + 1, outboundScheduleItems.Count);
            form_Reset();
        }

        private void btnPrev_Click(object sender, EventArgs e)
        {
            if (isModified)
            {
                DialogResult ret = MessageBox.Show("Are you sure to go previous page? The unsave data will be lost."
                    , "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button2);
                if (ret == DialogResult.No)
                    return;
            }
            currentItem--;
            lblPage.Text = String.Format("{0}/{1}", currentItem + 1, outboundScheduleItems.Count);
            form_Reset();
        }

        private void btnConfirm_Click(object sender, EventArgs e)
        {
            // update quantity to list
            int iComplete = 0;
            for (int i = 0; i < outboundItems.Count; i++)
            {
                lib.db.HT_OB ob = outboundItems.ElementAt(i);

                logger.Log("ob.id" + ob.__COLUMNS["id"]);
                if (ob.__COLUMNS["status"].Equals("Complete"))
                {
                    iComplete++;
                    continue; // skip if already complete
                }

                string status = "";
                int box_plan = int.Parse(ob.__COLUMNS["pkg_qty_plan"]);
                int box_act = int.Parse(ob.__COLUMNS["pkg_qty_act"].Equals(String.Empty) ? "0" : ob.__COLUMNS["pkg_qty_act"]);
                if (box_plan == box_act && !ob.__COLUMNS["status"].Equals("Complete"))
                {
                    status = "Complete";
                    iComplete++;
                }
                else if (box_plan > box_act && box_act > 0 && ob.__COLUMNS["status"].Equals(String.Empty))
                {
                    status = "Working";
                }

                logger.Log("status=" + status);

                if (!status.Equals(String.Empty))
                {
                    logger.Log("update column values");
                    outboundItems[i].__COLUMNS["status"] = status;
                    outboundItems[i].__COLUMNS["update_date"] = DateTime.Now.ToString("yyyyMMdd");
                    outboundItems[i].__COLUMNS["update_time"] = DateTime.Now.ToString("HHmmss");
                    outboundItems[i].__COLUMNS["update_by"] = Form_Login._Form_LoginInstance.userName;

                    logger.Log("update done");
                    Dictionary<string, string> cols = new Dictionary<string, string>(ob.__COLUMNS);
                    string id = cols["id"];
                    logger.Log("remove id from cols dict");
                    cols.Remove("id");
                    logger.Log("call update sql");
                    ob.set(cols, "id=" + id);
                }
            }

            if (iComplete == outboundItems.Count)
            {
                outboundScheduleItems[currentItem].Status = "Complete";
                btnConfirm.Enabled = false;
            }
            else if (iComplete > 0 && iComplete < outboundItems.Count)
            {
                outboundScheduleItems[currentItem].Status = "Working";
            }

            isModified = false;

            Form_OutboundSchedule.outboundScheduleItems = outboundScheduleItems;
            Form frm = new Form_Msg("Data save completed", Color.Black);
            frm.ShowDialog();

        }

        private void Form_Outbound_GotFocus(object sender, EventArgs e)
        {

            form_Reset();
        }

    }
}