using System;
using System.Drawing;
using System.Windows.Forms;

namespace AdvertsingProfitControl
{
    internal class AdvertisingProfitControlTableHelper
    {
        /// <summary>
        /// Paints rows according to their RowAttribute and detects whether or not they are part of a group.
        /// This function offers a faster method of determining all of this by starting at the row index that 
        /// fired the row leave even. As opposed to the PaintRowGroups function which spins through all the 
        /// DataGridView's rows.
        /// </summary>
        /// <param name="startingIndex">The starting index (the row that fired the RowLeave event)</param>
        /// <param name="dataGridView">The DataGridView to parse.</param>
        public void PaintRowGroupsFromIndex(int startingIndex, DataGridView dataGridView)
        {
            //Underflow protection for the lazy.
            if (startingIndex < 0)
            {
                return;
            }
            var parser = new RowParsing();
            int isHeaderColumn;
            int isMemberColumn;
            int isDirtyColumn;
            if (dataGridView.Columns.Count == Enum.GetNames(typeof(SalesTableColumns)).Length)
            {
                isHeaderColumn = (int) SalesTableColumns.IsHeaderRow;
                isMemberColumn = (int) SalesTableColumns.IsMemberRow;
                isDirtyColumn = (int) SalesTableColumns.IsDirty;
            }
            else
            {
                isHeaderColumn = (int)InventoryTableColumns.IsHeaderRow;
                isMemberColumn = (int)InventoryTableColumns.IsMemberRow;
                isDirtyColumn = (int) InventoryTableColumns.IsDirty;
            }
            //Spin through the dataGridView rows starting at the row that fired the event.
            for (var i = startingIndex; i < (dataGridView.RowCount - 1); i++)
            {
                //Get the status of the current row.
                var rowStatus = parser.GetRowAttribute(dataGridView.Rows[i]);
                //IF the current row is a header row...
                if (rowStatus == RowAttribute.HeaderRow)
                {
                    //Then check to see if the next row is a row header.
                    rowStatus = parser.GetRowAttribute(dataGridView.Rows[i + 1]);
                    //IF so, color code this row as White, since it is not a true group header.
                    if (rowStatus == RowAttribute.HeaderRow)
                    {
                        //Clear the current row of its attributes.
                        dataGridView.Rows[i].Cells[isHeaderColumn].Value = false;
                        dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
                        dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
                        return;
                    }
                    //IF the current row is not the first row in the data grid (index zero)...
                    if (i > 0)
                    {
                        //The start by checking the previous row's status.
                        rowStatus = parser.GetRowAttribute(dataGridView.Rows[i - 1]);
                        //IF the previous row is a header row AND has color coding saying it is a group header, then clear the previous row's color and apply it to this row (i).
                        if (rowStatus == RowAttribute.HeaderRow && (bool)dataGridView.Rows[i - 1].Cells[isHeaderColumn].EditedFormattedValue)
                        {
                            //Clear the previous row of its attributes.
                            dataGridView.Rows[i - 1].Cells[isHeaderColumn].Value = false;
                            dataGridView.Rows[i - 1].Cells[isMemberColumn].Value = false;
                            //This condition means the user changed the members of a group, so the old header row needs to be updated in the database.
                            dataGridView.Rows[i - 1].Cells[isDirtyColumn].Value = true;
                            dataGridView.Rows[i - 1].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            dataGridView.Rows[i - 1].DefaultCellStyle.BackColor = Color.White;
                            //Check the next row to see if its a member row before declaring the current row a header row.
                            rowStatus = parser.GetRowAttribute(dataGridView.Rows[i + 1]);
                            if (rowStatus != RowAttribute.MemberRow)
                            {
                                //Clear the coloring from the current row.
                                dataGridView.Rows[i].Cells[isHeaderColumn].Value = true;
                                dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
                                dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
                                return;
                            }
                            //Set the current row as a header row.
                            dataGridView.Rows[i].Cells[isHeaderColumn].Value = true;
                            dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
                            dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.LightGray;
                            return;
                        }
                        //IF the previous row is a header row OR if the previous row is index zero AND a member row, clear its coloring.
                        if (rowStatus == RowAttribute.HeaderRow || rowStatus == RowAttribute.MemberRow && (i - 1) == 0)
                        {
                            //Clear the previous row of its attributes.
                            dataGridView.Rows[i - 1].Cells[isHeaderColumn].Value = false;
                            dataGridView.Rows[i - 1].Cells[isMemberColumn].Value = false;
                            dataGridView.Rows[i - 1].DefaultCellStyle.BackColor = Color.White;
                        }
                        //Then check to see if the next row is a member row
                        rowStatus = parser.GetRowAttribute(dataGridView.Rows[i + 1]);
                        if (rowStatus == RowAttribute.MemberRow)
                        {
                            //Set the current row and check for changes.
                            if (!(bool)dataGridView.Rows[i].Cells[isHeaderColumn].EditedFormattedValue)
                            {
                                dataGridView.Rows[i].Cells[isDirtyColumn].Value = true;
                                dataGridView.Rows[i].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            }
                            dataGridView.Rows[i].Cells[isHeaderColumn].Value = true;
                            dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
                            dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.LightGray;
                            //Set the next row as a member row.
                            if (!(bool)dataGridView.Rows[i + 1].Cells[isMemberColumn].EditedFormattedValue)
                            {
                                dataGridView.Rows[i + 1].Cells[isDirtyColumn].Value = true;
                                dataGridView.Rows[i + 1].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            }
                            dataGridView.Rows[i + 1].Cells[isHeaderColumn].Value = false;
                            dataGridView.Rows[i + 1].Cells[isMemberColumn].Value = true;
                            dataGridView.Rows[i + 1].DefaultCellStyle.BackColor = Color.LightBlue;
                        }
                        //IF previous row is Incomplete, then call the stable PaintRowGroups function.
                        else if (rowStatus == RowAttribute.IncompleteRow)
                        {
                            PaintRowGroups(dataGridView);
                        }
                    }
                    else
                    {
                        //Then check to see if the next row is a member row
                        rowStatus = parser.GetRowAttribute(dataGridView.Rows[i + 1]);
                        if (rowStatus == RowAttribute.MemberRow)
                        {
                            //Set the current row and check for changes.
                            if (!(bool)dataGridView.Rows[i].Cells[isHeaderColumn].EditedFormattedValue)
                            {
                                dataGridView.Rows[i].Cells[isDirtyColumn].Value = true;
                                dataGridView.Rows[i].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            }
                            dataGridView.Rows[i].Cells[isHeaderColumn].Value = true;
                            dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
                            dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.LightGray;
                            //Set the next row as a member row.
                            if (!(bool)dataGridView.Rows[i + 1].Cells[isMemberColumn].EditedFormattedValue)
                            {
                                dataGridView.Rows[i + 1].Cells[isDirtyColumn].Value = true;
                                dataGridView.Rows[i + 1].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            }
                            dataGridView.Rows[i + 1].Cells[isHeaderColumn].Value = false;
                            dataGridView.Rows[i + 1].Cells[isMemberColumn].Value = true;
                            dataGridView.Rows[i + 1].DefaultCellStyle.BackColor = Color.LightBlue;
                        }
                    }
                }
                else if (rowStatus == RowAttribute.MemberRow)
                {
                    if (i > 0)
                    {
                        //Check the previous row.
                        rowStatus = parser.GetRowAttribute(dataGridView.Rows[i - 1]);
                        //IF the previous row is a member row AND is the first row in the data grid, then remove the coloring from it and the current row (i).
                        if (rowStatus == RowAttribute.MemberRow && (i - 1) == 0)
                        {
                            //Clear the previous row of its attributes.
                            dataGridView.Rows[i - 1].Cells[isHeaderColumn].Value = false;
                            dataGridView.Rows[i - 1].Cells[isMemberColumn].Value = false;
                            dataGridView.Rows[i - 1].DefaultCellStyle.BackColor = Color.White;
                            //Check for changes in the current row.
                            if ((bool) dataGridView.Rows[i].Cells[isMemberColumn].EditedFormattedValue)
                            {
                                dataGridView.Rows[i].Cells[isDirtyColumn].Value = true;
                                dataGridView.Rows[i].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            }
                            //Clear the current row of its attributes.                           
                            dataGridView.Rows[i].Cells[isHeaderColumn].Value = false;
                            dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
                            dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
                        }
                        //IF the previous row is a member row AND it also has color coding suggesting that it is a member of a group, then add the current row (i) as well.
                        else if (rowStatus == RowAttribute.MemberRow && (bool)dataGridView.Rows[i - 1].Cells[isMemberColumn].EditedFormattedValue)
                        {
                            //Check for changes in the current row.
                            if (!(bool)dataGridView.Rows[i].Cells[isMemberColumn].EditedFormattedValue)
                            {
                                dataGridView.Rows[i].Cells[isDirtyColumn].Value = true;
                                dataGridView.Rows[i].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            }
                            //Set the current row as a member row.
                            dataGridView.Rows[i].Cells[isHeaderColumn].Value = false;
                            dataGridView.Rows[i].Cells[isMemberColumn].Value = true;
                            dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.LightBlue;
                        }
                        //IF the previous row is simply a member row with no coloring at all, then remove the coloring from the current row (i).
                        else if (rowStatus == RowAttribute.MemberRow || rowStatus == RowAttribute.AdSpecialRow)
                        {
                            //Check for changes in the current row.
                            if ((bool)dataGridView.Rows[i].Cells[isMemberColumn].EditedFormattedValue)
                            {
                                dataGridView.Rows[i].Cells[isDirtyColumn].Value = true;
                                dataGridView.Rows[i].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            }
                            //Clear the current row of its attributes.
                            dataGridView.Rows[i].Cells[isHeaderColumn].Value = false;
                            dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
                            dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
                        }
                        //IF the previous row is a header row, then color it as a group header and color the current row as a member of said group.
                        else if (rowStatus == RowAttribute.HeaderRow && !(bool)dataGridView.Rows[i - 1].Cells[isHeaderColumn].EditedFormattedValue)
                        {
                            //Set the previous row as a header row.
                            if (!(bool)dataGridView.Rows[i - 1].Cells[isMemberColumn].EditedFormattedValue)
                            {
                                dataGridView.Rows[i - 1].Cells[isDirtyColumn].Value = true;
                                dataGridView.Rows[i - 1].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            }
                            dataGridView.Rows[i - 1].Cells[isHeaderColumn].Value = true;
                            dataGridView.Rows[i - 1].Cells[isMemberColumn].Value = false;
                            dataGridView.Rows[i - 1].DefaultCellStyle.BackColor = Color.LightGray;
                            //This condition means the user created a group so the newly made header row will need to be updated in the database as well.
                            dataGridView.Rows[i - 1].Cells[isDirtyColumn].Value = true;
                            dataGridView.Rows[i - 1].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            //Check for changes in the current row.
                            if (!(bool)dataGridView.Rows[i].Cells[isMemberColumn].EditedFormattedValue)
                            {
                                dataGridView.Rows[i].Cells[isDirtyColumn].Value = true;
                                dataGridView.Rows[i].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            }
                            //Set the current row as a member row.
                            dataGridView.Rows[i].Cells[isHeaderColumn].Value = false;
                            dataGridView.Rows[i].Cells[isMemberColumn].Value = true;
                            dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.LightBlue;
                        }
                        else if (rowStatus == RowAttribute.HeaderRow)
                        {
                            //Check for changes in the current row.
                            if (!(bool)dataGridView.Rows[i].Cells[isMemberColumn].EditedFormattedValue)
                            {
                                dataGridView.Rows[i].Cells[isDirtyColumn].Value = true;
                                dataGridView.Rows[i].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                            }
                            //Set the current row as a member row.
                            dataGridView.Rows[i].Cells[isHeaderColumn].Value = false;
                            dataGridView.Rows[i].Cells[isMemberColumn].Value = true;
                            dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.LightBlue;
                        }
                        //IF the previous row is incomplete, then call the stable PaintRowGroups function.
                        else if (rowStatus == RowAttribute.IncompleteRow)
                        {
                            PaintRowGroups(dataGridView);
                        }
                    }
                    //ELSE the current row is the first row in the data grid, therefore it can't be a member row so remove all coloring.
                    else
                    {
                        //Clear the current row of its attributes.
                        dataGridView.Rows[0].Cells[isHeaderColumn].Value = false;
                        dataGridView.Rows[0].Cells[isMemberColumn].Value = false;
                        dataGridView.Rows[0].DefaultCellStyle.BackColor = Color.White;
                    }
                }
                else if (rowStatus == RowAttribute.AdSpecialRow)
                {
                    if(i == 0) return;
                    dataGridView.Rows[startingIndex].DefaultCellStyle.BackColor = Color.Silver;
                    //Get the previous row's attribute.
                    rowStatus = parser.GetRowAttribute(dataGridView.Rows[i - 1]);
                    if (rowStatus == RowAttribute.HeaderRow)
                    {
                        //Check to see if the previous row sees itself as a header row, if so mark it dirty.
                        if ((bool)dataGridView.Rows[i - 1].Cells[isHeaderColumn].EditedFormattedValue)
                        {
                            dataGridView.Rows[i - 1].Cells[isDirtyColumn].Value = true;
                            dataGridView.Rows[i - 1].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                        }
                        //Clear its color coding.
                        dataGridView.Rows[i - 1].Cells[isHeaderColumn].Value = false;
                        dataGridView.Rows[i - 1].Cells[isMemberColumn].Value = false;
                        dataGridView.Rows[i - 1].DefaultCellStyle.BackColor = Color.White;
                    }
                    //Next get the status of the next row.
                    rowStatus = parser.GetRowAttribute(dataGridView.Rows[i + 1]);
                    if (rowStatus == RowAttribute.MemberRow)
                    {
                        //Check to see if the next row thinks it is a member row.
                        if (!(bool)dataGridView.Rows[i + 1].Cells[isMemberColumn].EditedFormattedValue)
                        {
                            dataGridView.Rows[i + 1].Cells[isDirtyColumn].Value = true;
                            dataGridView.Rows[i + 1].HeaderCell.Style.BackColor = ApplicationColors.PendingEdit;
                        }
                        //Clear its color coding.
                        dataGridView.Rows[i + 1].Cells[isMemberColumn].Value = false;
                        dataGridView.Rows[i + 1].Cells[isHeaderColumn].Value = false;
                        dataGridView.Rows[i + 1].DefaultCellStyle.BackColor = Color.White;
                    }
                }
            }
        }

        public void PaintRowGroups(DataGridView dataGridView)
        {
            var parser = new RowParsing();
            var incompleteRowsFound = 0;
            var lastHeaderIndex = -1;
            var i = 0;
            var adSpecialIndex = -1;

            foreach (DataGridViewRow row in dataGridView.Rows)
            {
                //Get the current row's status.
                var rowType = parser.GetRowAttribute(row);
                //If the current row is not a group header, the first row in the grid, or a new row and in fact a member row...
                if (i != 0 && rowType == RowAttribute.MemberRow && !row.IsNewRow && rowType != RowAttribute.IncompleteRow)
                {
                    //Remove all coloring on the current row.
                    dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;

                    //Check to make sure the numbers are within bounds, errors occurs when an incomplete row is found at index zero (0), and the current row is one (1).
                    if ((i - (1 + incompleteRowsFound)) > 0)
                    {
                        //Check to see if the previous row is a header row by subtracting the number of rows that are (incomplete + 1) from the total number of rows (i).
                        //Adding one (1) to the incomplete count allows for checking the row right before the first incomplete row found so far to see if it's a header row.
                        if (parser.GetRowAttribute(dataGridView.Rows[i - (1 + incompleteRowsFound)]) == RowAttribute.HeaderRow)
                        {
                            row.DefaultCellStyle.BackColor = Color.LightBlue;   //Group member
                            dataGridView.Rows[lastHeaderIndex].DefaultCellStyle.BackColor = Color.LightGray;   //Group header
                        }
                        //Else if a header row was not found from the previous operation but a header row is set, then its safe to assume that this row can be a member.
                        else if (lastHeaderIndex >= 0)
                        {
                            //Check to make sure that the last header index is underneath the Ad Special Row OR that the current row (i) is before the Ad Special Index.
                            if (lastHeaderIndex > adSpecialIndex || i < adSpecialIndex)
                            {
                                //Assume that the current row is a member of that group header and color it as such.
                                row.DefaultCellStyle.BackColor = Color.LightBlue;
                            }
                        }
                    }
                }
                //If the current row is a potential group header AND the next row is as well remove the coloring from the current row, no need for checks.
                else if (rowType == RowAttribute.HeaderRow && parser.GetRowAttribute(dataGridView.Rows[i + 1]) == RowAttribute.HeaderRow)
                {
                    dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
                }
                //Check to see if this row is the first row, a header index row, AND the next row is a MemberRow.
                else if (rowType == RowAttribute.HeaderRow && parser.GetRowAttribute(dataGridView.Rows[i + 1]) == RowAttribute.MemberRow && i == 0)
                {
                    //IF so, set the last header index, and color code of this row along with the next row which is a MemberRow.
                    lastHeaderIndex = 0;
                    dataGridView.Rows[0].DefaultCellStyle.BackColor = Color.LightGray;
                    dataGridView.Rows[i + 1].DefaultCellStyle.BackColor = Color.LightBlue;
                }
                //Check to see if this row is a group header.
                else if (rowType == RowAttribute.HeaderRow)
                {
                    //If so, reset the incomplete rows found count, set the lastHeaderIndex to this row's index (i) and change it's color to white.
                    incompleteRowsFound = 0;
                    lastHeaderIndex = i;
                    dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
                }
                //If the current row is the first row in the grid AND is not a group header then remove all color from it, since its not allowed to be a header or a member.
                else if (i == 0 && rowType == RowAttribute.MemberRow)
                {
                    dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
                }
                //Mark an incomplete row to determine whether or not we found one and remove any coloring it may have, incomplete rows are not allowed to be members or headers.
                if (rowType == RowAttribute.IncompleteRow)
                {
                    incompleteRowsFound++;
                    dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
                }
                //
                if (rowType == RowAttribute.AdSpecialRow)
                {
                    adSpecialIndex = i;
                    dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.Silver;
                }
                i++;
            }//end for-each
            dataGridView.Refresh();
        }//End PaintRowGroups
    }

    public enum SalesTableColumns
    {
        Id = 0,
        AdItem = 1,
        Sold = 2,
        SalePrice = 3,
        TotalSales = 4,
        Cost = 5,
        ProfitReturn = 6,
        TotalProfitReturn = 7,
        IsHeaderRow = 8,
        IsMemberRow = 9,
        IsDirty = 10
    }

    public enum InventoryTableColumns
    {
        Id = 0,
        AdItem = 1,
        BeginningInventory = 2,
        Recieved = 3,
        Total = 4,
        EndingInventory = 5,
        IsHeaderRow = 6,
        IsMemberRow = 7,
        IsDirty = 8
    }

    public enum InvoiceTableColumns
    {
        Id = 0,
        InvoiceDate = 1,
        Supplier = 2,
        InvoiceNumber = 3,
        InvoiceNetAmountAtCost = 4,
        InvoiceNetAmount = 5,
        InvoiceNote = 6,
        IsDirty = 7
    }
}
