using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;


namespace pmsDataGridView
{
    public class SaleRecord
    {
        public enum SaleColumnType { ID, NAME, EMAIL, DATE, PAYABLE, PURCHASEEMAIL, PACKED, PAID, SENTEMAIL, INDEX }
        public enum SaleSourceType { UNKNOWN, TRADEME, WEBSITE, DIRECTCONTACT }
        //DIRECTCONTACT = PHONE, EMAIL ETC
        #region Constructor and Destructor
        
        public SaleRecord() { }

        /*
        public SaleRecord(double shippingpayable, double shippingcost, double promotioncost, ProductList bearingorder, Customer buyer, int discount, string comment)
        {
            this.pDate = DateTime.Now; //stamp the current tiime when the sale is lodged
            //this.pPaid = false; //not paid soon after the sale is lodged, as default
            this.pShippingCost = shippingcost;
            this.pPromotionCost = promotioncost;
            this.BearingOrder = bearingorder;
            this.Buyer = buyer;            
            this.Discount = discount;
            this.Comment = comment;
            this.ShippingPayable = shippingpayable;
            this.CustomerName = buyer.Name;
            this.CustomerIndex = buyer.Index;
            //work out total payable
            double total_payable = 0.0;
            //sums up the cost of the ordered bearings
            for (int last_sale_index = 0; last_sale_index < bearingorder.Count; last_sale_index++)
            {
                total_payable += bearingorder.Bearings[last_sale_index].Price * bearingorder.Bearings[last_sale_index].quantity;
            }
            //discount
            total_payable = total_payable * (1 - 0.01 * discount);
            //add the shipping cost
            total_payable += shippingpayable;
            this.pPayable = total_payable;

            //Work out the ID
            this.ID = pDate.Year + pDate.Month.ToString("00") + pDate.Day.ToString("00") + pDate.Hour.ToString("00")
                + pDate.Minute.ToString("00") + pDate.Second.ToString("00");

            //Work out the revenue
            updateRevenue();
        }
        */
        //this is the old constructor used solely by the old SaleEditForm.cs
        public SaleRecord(double shippingpayable, double shippingcost, double promotioncost, ProductList bearingorder, string customername, int discount, string comment) 
        {
            this.pDate = DateTime.Now; //stamp the current tiime when the sale is lodged
            //this.pPaid = false; //not paid soon after the sale is lodged, as default
            this.pShippingCost = shippingcost;
            this.pPromotionCost = promotioncost;            
            this.BearingOrder = bearingorder;            
            //this.Buyer = buyer;
            this.CustomerName = customername;
            this.Discount = discount;
            this.Comment = comment;
            this.ShippingPayable = shippingpayable;
            //work out total payable
            double total_payable = 0.0;
            //sums up the cost of the ordered bearings
            for (int i = 0; i < bearingorder.Count; i++)
            {
                total_payable += bearingorder.Bearings[i].Price * bearingorder.Bearings[i].quantity;
            }
            //discount
            total_payable = total_payable * (1 - 0.01 * discount);
            //add the shipping cost
            total_payable += shippingpayable;
            this.pPayable = total_payable;

            //Work out the ID
            this.ID = pDate.Year + pDate.Month.ToString("00") + pDate.Day.ToString("00") + pDate.Hour.ToString("00")
                + pDate.Minute.ToString("00") + pDate.Second.ToString("00");
           
            
            //Work out the revenue
            updateRevenue();
        }

        //this is the new constructor used by the SaleEditForm_v2.cs
        public SaleRecord(double shippingpayable, double shippingcost, double promotioncost, ProductList bearingorder, int customer_index, int discount, string comment)
        {
            this.pDate = DateTime.Now; //stamp the current time when the sale is lodged            
            this.pShippingCost = shippingcost;
            this.pPromotionCost = promotioncost;
            this.BearingOrder = bearingorder;            
            this.CustomerIndex = customer_index;
            this.Discount = discount;
            this.Comment = comment;
            this.ShippingPayable = shippingpayable;
            

            //Work out the ID
            this.ID = pDate.Year + pDate.Month.ToString("00") + pDate.Day.ToString("00") + pDate.Hour.ToString("00")
                + pDate.Minute.ToString("00") + pDate.Second.ToString("00");

            updatePayable();
            //Work out the revenue
            updateRevenue();
        }

        ~SaleRecord() { }

        #endregion

        //public enum SealType { OneSideMetal, BothSideMetal, OneSidePlastic, BothSidePlastic, BothSideMetalandPlastic }
        //public enum BrandType { Normal, NMB, NSK, KOYO, MIX }

        
        #region Properties

        [XmlElement("Purchase_Date")]
        public DateTime Date 
        {
            get {return pDate;}
            set { pDate = value; }
        }

        [XmlElement("Paid")]
        public bool Paid
        {
            get { return pPaid; }
            set { pPaid = value; }
        }

        [XmlElement("Promotion_Cost")]
        public double PromotionCost
        {
            get { return pPromotionCost; }
            set { pPromotionCost = value; }
        }

        [XmlElement("Shipping_Cost")]
        public double ShippingCost
        {
            get { return pShippingCost; }
            set { pShippingCost = value; }
        }

        [XmlElement("Payable")]
        public double Payable
        {
            get { return pPayable; }
            set { pPayable = value; }
        }

        [XmlElement("Net_Profit")]
        public double Revenue
        {
            get { return pNetProfit; }
            set { pNetProfit= value; }
        } 
        #endregion

        //Methods
        public void updatePayable()
        {
            //work out total payable
            double total_payable = 0.0;
            //sums up the cost of the ordered bearings
            for (int i = 0; i < BearingOrder.Count; i++)
            {
                total_payable += BearingOrder.Bearings[i].Price * BearingOrder.Bearings[i].quantity;
            }
            //discount
            Discount_amount = total_payable * 0.01 * Discount;
            total_payable = total_payable - Discount_amount;
            //add the shipping cost
            total_payable += ShippingPayable;
            this.pPayable = total_payable;
        }
        public void updateRevenue()
        {
            this.Revenue = pPayable - pShippingCost - pPromotionCost; //Note, it doesn't incl bearing prime cost
            //also note, pPayable incl shipping payable
        }
        public void fill_to_row_i(System.Windows.Forms.DataGridView SaleLogGrid, CustomerList customerlist, int i)
        {//This function fills sale on a row, either replace an old sale or to add a new sale. 
            //need to add a new row before calling this function if adding a new sale
            //when it's filling a sale to list, maybe due to search results, doesn't consider to change of value 
            //for the cell, hence shouldn't trigger SaleLogGrid_CellValueChanged
            Filling_a_sale_to_list = true;
            //if not enought rows, add more
            if (i == SaleLogGrid.Rows.Count)
            {
                SaleLogGrid.Rows.Add();
            }
            //productlist.Bearings[last_sale_index].Index = last_sale_index; //reset all the indices
            SaleLogGrid.Rows[i].Cells[(int)SaleColumnType.ID].Value = this.ID;
            SaleLogGrid.Rows[i].Cells[(int)SaleColumnType.NAME].Value = customerlist[this.CustomerIndex].Name;
            SaleLogGrid.Rows[i].Cells[(int)SaleColumnType.EMAIL].Value = customerlist[this.CustomerIndex].Email;
            SaleLogGrid.Rows[i].Cells[(int)SaleColumnType.DATE].Value = this.Date.ToLongDateString();
            SaleLogGrid.Rows[i].Cells[(int)SaleColumnType.PAYABLE].Value = this.Payable.ToString("0.00");
            SaleLogGrid.Rows[i].Cells[(int)SaleColumnType.PURCHASEEMAIL].Value = this.PurchaseEmail;
            SaleLogGrid.Rows[i].Cells[(int)SaleColumnType.PAID].Value = this.Paid;
            SaleLogGrid.Rows[i].Cells[(int)SaleColumnType.PACKED].Value = this.Shipped;
            SaleLogGrid.Rows[i].Cells[(int)SaleColumnType.SENTEMAIL].Value = this.SentEmail;
            SaleLogGrid.Rows[i].Cells[(int)SaleColumnType.INDEX].Value = this.Index.ToString();
            Filling_a_sale_to_list = false;  
        }

        //Variables      
        public string trackingNumber = null;
        private DateTime pDate;
        public DateTime packedDate;
        public DateTime shippedDate;
        public DateTime paidConfirmedDate;
        private bool pPaid=false;
        private double pShippingCost=0.0;
        private double pPromotionCost=0.0;
        private double pPayable=0.0;
        private double pNetProfit=0.0;       
        public ProductList BearingOrder;
        //public Customer Buyer;
        public string CustomerName; // don't needed 
        public int CustomerIndex = 0;
        public string ID = "";
        public int Index = -1;
        public double ShippingPayable = 0.0;
        public string Comment;
        public bool Shipped = false; //when created, Shipped is false by default
        public int Discount = 0; //in percentage %
        public double Discount_amount = 0;
        public bool PurchaseEmail = false;
        public bool SentEmail = false;
        public static bool Filling_a_sale_to_list = false;
        public SaleSourceType Source = SaleSourceType.UNKNOWN;
    }

    public class SaleLogList
    {
        #region Constructor and Distructor
        public SaleLogList()
        {
            SaleLoglist = new ArrayList();
        }
        ~SaleLogList() { }
        #endregion

        #region Methods

        public void add(SaleRecord s)
        {
            SaleLoglist.Add(s);
            //s.Index = Count - 1;
        }

        public SaleRecord get_SaleLog(int location) //0 based index  
        {
            if (location < SaleLoglist.Count)
            {
                return (SaleRecord)SaleLoglist[location];
            }
            else return null;
        }

        public void fill_grid(System.Windows.Forms.DataGridView SaleLogGrid, CustomerList customerlist)
        {
            for (int i = 0; i < Count; i++)
            {
                SaleRecord s = this[i];
                //SaleLogGrid.Rows.Add();
                s.fill_to_row_i(SaleLogGrid, customerlist, i);                
            }
        }

        public int Count
        {
            get { return SaleLoglist.Count; }
        }

        public void remove(int location) //0 based index  
        {
            if (location < SaleLoglist.Count)
            {
                SaleLoglist.RemoveAt(location);
                
                for (int i = location; i < Count; i++) //decrement indices of salerecords after 'location' 
                {
                    this[i].Index--;
                }
                 
            }
            else return;
        }

        public void copy(SaleLogList sample)
        {
            this.SaleLoglist = sample.SaleLoglist;
        }

        //Indexer
        public SaleRecord this[int location]
        {
            get { return (SaleRecord)SaleLoglist[location]; }
            set { SaleLoglist[location] = value; }
        }

        [XmlIgnore]
        public string data_path
        {
            get { return FilePath; }
            set { FilePath = value; }
        }

        #endregion

        #region XML read and write methods

        [XmlElement("Sale")]
        //this is a property, when use: item.items[0], returns an item
        public SaleRecord[] SaleRecords
        {
            get
            {
                SaleRecord[] salerecords = new SaleRecord[SaleLoglist.Count];
                SaleLoglist.CopyTo(salerecords);
                return salerecords;
            }

            set
            {
                if (value == null) return;
                SaleRecord[] salerecords = (SaleRecord[])value;
                SaleLoglist.Clear();
                foreach (SaleRecord b in salerecords)
                {
                    SaleLoglist.Add(b);
                }
            }
        } 

        public virtual void save()
        {

            // Serialization
            XmlSerializer ser = new XmlSerializer(typeof(SaleLogList));
            TextWriter xml_write = new StreamWriter(FilePath);

            ser.Serialize(xml_write, this);
            xml_write.Close();
        }

        public virtual void load()
        {
            SaleLogList temp = new SaleLogList();
            // Deserialization

            XmlSerializer ser = new XmlSerializer(typeof(SaleLogList));

            if (FilePath != null && File.Exists(FilePath))
            {
                TextReader xml_read = new StreamReader(FilePath);

                temp = (SaleLogList)ser.Deserialize(xml_read);

                copy(temp);
                xml_read.Close();
            }
            else //dont find the xml file, so creat an empty sell list anyway
            {
                copy(temp);
            }
        }

        #endregion

        #region Private variables

        private ArrayList SaleLoglist;
        private string FilePath = @"../../ProgramData/SaleData.xml";

        #endregion
 
  

    }
}
