using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Transactions;
using System.Windows.Forms;

namespace AdvertsingProfitControl
{
    internal class DatabaseWriter
    {
        private readonly OleDbConnection _oleDbConnection = new OleDbConnection();
        private readonly FrmLogConsole _logConsole = FrmLogConsole.GetStaticInstance;
        public DatabaseWriter(string connectionString)
        {
            _oleDbConnection.ConnectionString = connectionString;
        }
        #region New Code

        /// <summary>
        /// Inserts new records into the specified sales table.
        /// Supports rolling back the database to prevent corruption.
        /// </summary>
        /// <param name="salesTable">The data table that contains the data to be inserted.</param>
        /// <param name="connectionString"></param>
        /// <returns></returns>
        public Dictionary<int, int> InsertIntoSalesTable(DataTable salesTable, string connectionString)
        {
            var rowIndex = 0;
            var rows = new Dictionary<int, int>();
            var oleDbConnection = new OleDbConnection(connectionString);
            //IDs from the database can not be zero (0), so this will be the default value (no group).
            var oleDbCommand = new OleDbCommand
            {
                Connection = oleDbConnection
            };
            OleDbTransaction oleDbTransaction = null;
            try
            {
                oleDbConnection.Open();
                oleDbTransaction = oleDbConnection.BeginTransaction();
                oleDbCommand.Transaction = oleDbTransaction;
                for (var i = 0; i < salesTable.Rows.Count; i++)
                {
                    oleDbCommand.CommandText =
                        "INSERT INTO " + salesTable.TableName + " (Sold, SalePrice, TotalSales, Cost, ProfitReturn, TotalProfitReturn, FK_AdItemID, RowAttribute, FK_AdSpecialGroupName, RowPosition, FK_DateID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
                    //New Sales Table Layout (Based on the Database's Physical Layout)
                    //0: Sold 1:SalePrice 2:TotalSales 3:cost 4:ProfitReturn 5:TotalProfitReturn
                    //6:FK_AdItemID 7:RowAttribute 8:FK_AdSpecialGroupName (ID) 9:RowPosition (not index based)
                    //10:FK_DateID
                    oleDbCommand.Parameters.AddWithValue("Sold", salesTable.Rows[i][0]);
                    oleDbCommand.Parameters.AddWithValue("SalesPrice", salesTable.Rows[i][1]);
                    oleDbCommand.Parameters.AddWithValue("TotalSales", salesTable.Rows[i][2]);
                    oleDbCommand.Parameters.AddWithValue("Cost", salesTable.Rows[i][3]);
                    oleDbCommand.Parameters.AddWithValue("ProfitReturn", salesTable.Rows[i][4]);
                    oleDbCommand.Parameters.AddWithValue("TotalProfitReturn", salesTable.Rows[i][5]);
                    oleDbCommand.Parameters.AddWithValue("adItemID", int.Parse(salesTable.Rows[i][6].ToString()));
                    oleDbCommand.Parameters.AddWithValue("RowAttribute", int.Parse(salesTable.Rows[i][7].ToString()));
                    oleDbCommand.Parameters.AddWithValue("adSpecialID", int.Parse(salesTable.Rows[i][8].ToString()));                    
                    oleDbCommand.Parameters.AddWithValue("RowPosition", int.Parse(salesTable.Rows[i][9].ToString()));
                    oleDbCommand.Parameters.AddWithValue("dateID", salesTable.Rows[i][10]);
                    oleDbCommand.ExecuteNonQuery();
                    oleDbCommand.Parameters.Clear();
                    rowIndex++;
                }
                oleDbTransaction.Commit();
                foreach (DataRow row in salesTable.Rows)
                {
                    var rowId = RetrieveRowId(salesTable.TableName, int.Parse(row[6].ToString()), int.Parse(row[10].ToString()));
                    if (int.Parse(row[8].ToString()) != 0)
                    {
                        //Account for the ad special row.
                        rows.Add(int.Parse(row[9].ToString()) + 1, rowId);
                    }
                    else
                    {
                        rows.Add(int.Parse(row[9].ToString()), rowId);
                    } 
                }
            }
            catch (OleDbException ex)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to write to database: " + ex.Message);
                if (rowIndex <= 0)
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Failed to begin parsing data rows, var dump of erroneous row unavailable.");
                }
                else
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Failed on row " + (rowIndex + 1) + " due to the above error. Dumping contents of row " + (rowIndex + 1) +  " from " + salesTable.TableName + ".");
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Ad Item ID: \"" +
                        salesTable.Rows[rowIndex][6] + "\" Sold: \"" + salesTable.Rows[rowIndex][0] + "\"");
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Sale Price: \"" + salesTable.Rows[rowIndex][1] + "\" Total Sales: \"" + salesTable.Rows[rowIndex][2] + "\"");
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Cost: \"" + salesTable.Rows[rowIndex][3] + "\" Profit Return: \"" + salesTable.Rows[rowIndex][4] + "\"");
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Total Profit Return: \"" +
                        salesTable.Rows[rowIndex][5] + "\" Ad Special Group: \"" + salesTable.Rows[rowIndex][8] + "\"");             
                }
                oleDbTransaction?.Rollback();
                _logConsole.WriteToLog(FrmLogConsole.Level.Critical, "Rollback completed successfully, " + salesTable.TableName+ " table failed on insertion.");
            }
            finally
            {
                _oleDbConnection.Close();
            }
            return rows;
        }

        public bool UpdateSalesTable(DataTable salesTable, string connectionString)
        {
            var wasSuccessful = false;
            var rowIndex = 0;
            var oleDbConnection = new OleDbConnection(connectionString);
            //IDs from the database can not be zero (0), so this will be the default value (no group).
            var oleDbCommand = new OleDbCommand
            {
                Connection = oleDbConnection
            };
            OleDbTransaction oleDbTransaction = null;
            try
            {
                oleDbTransaction = oleDbConnection.BeginTransaction();
                _oleDbConnection.Open();
                oleDbCommand.Transaction = oleDbTransaction;
                for (var i = 0; i < salesTable.Rows.Count; i++)
                {
                    oleDbCommand.CommandText =
                        "UPDATE " + salesTable.TableName + " SET Sold = ?, SalePrice = ?, TotalSales = ?, Cost = ?, ProfitReturn = ?, TotalProfitReturn = ?, RowAttribute = ?, FK_AdSpecialGroupName = ?, RowPosition = ? WHERE ID = ?";
                    //Update Sales Table Layout (Based on the Database's Physical Layout)
                    //0:ID 1:Sold 2:SalePrice 3:TotalSales 4:cost 5:ProfitReturn 6:TotalProfitReturn
                    //7:FK_AdItemID 8:RowAttribute 9:FK_AdSpecialGroupName (ID) 10:RowPosition (not index based)
                    //11:FK_DateID
                    oleDbCommand.Parameters.AddWithValue("Sold", salesTable.Rows[i][1]);
                    oleDbCommand.Parameters.AddWithValue("SalesPrice", salesTable.Rows[i][2]);
                    oleDbCommand.Parameters.AddWithValue("TotalSales", salesTable.Rows[i][3]);
                    oleDbCommand.Parameters.AddWithValue("Cost", salesTable.Rows[i][4]);
                    oleDbCommand.Parameters.AddWithValue("ProfitReturn", salesTable.Rows[i][5]);
                    oleDbCommand.Parameters.AddWithValue("TotalProfitReturn", salesTable.Rows[i][6]);
                    oleDbCommand.Parameters.AddWithValue("RowAttribute", salesTable.Rows[i][8]);
                    oleDbCommand.Parameters.AddWithValue("adSpecialID", salesTable.Rows[i][9]);
                    oleDbCommand.Parameters.AddWithValue("RowPosition", salesTable.Rows[i][10]);
                    oleDbCommand.Parameters.AddWithValue("ID", salesTable.Rows[i][0]);
                    oleDbCommand.ExecuteNonQuery();
                    oleDbCommand.Parameters.Clear();
                    rowIndex++;
                }
                oleDbTransaction.Commit();
                wasSuccessful = true;
            }
            catch (OleDbException ex)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to update the database for " + salesTable.TableName + ": " + ex.Message);
                if (rowIndex <= 0)
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Failed to begin parsing data rows, var dump of erroneous row unavailable.");
                }
                else
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Failed on row " + (rowIndex + 1) + " due to the above error. Dumping contents of row " + (rowIndex + 1) + " from " + salesTable.TableName + ".");
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Ad Item ID: \"" +
                        salesTable.Rows[rowIndex][7] + "\" Sold: \"" + salesTable.Rows[rowIndex][1] + "\"");
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Sale Price: \"" + salesTable.Rows[rowIndex][2] + "\" Total Sales: \"" + salesTable.Rows[rowIndex][3] + "\"");
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Cost: \"" + salesTable.Rows[rowIndex][4] + "\" Profit Return: \"" + salesTable.Rows[rowIndex][5] + "\"");
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Total Profit Return: \"" +
                        salesTable.Rows[rowIndex][6] + "\" Ad Special Group: \"" + salesTable.Rows[rowIndex][9] + "\"");
                }
                oleDbTransaction?.Rollback();
                _logConsole.WriteToLog(FrmLogConsole.Level.Critical, "Rollback completed successfully, " + salesTable.TableName + " table failed on update.");
            }
            finally
            {
                _oleDbConnection.Close();
            }

            return wasSuccessful;
        }

        /// <summary>
        /// Inserts a new ad item into the database and returns the new item's ID number.
        /// Supports rolling back as to not corrupt the database.
        /// </summary>
        /// <param name="adItemName">The ad item's name that is to be added.</param>
        /// <param name="oleDbCommand">A reference to a command that already has a transaction active.</param>
        /// <returns>The ID number of the ad item that was just added.</returns>
        public int InsertNewAdItem(string adItemName, OleDbCommand oleDbCommand = null)
        {
            var adItemId = 0;
            var needsTransaction = false;
            if (oleDbCommand == null)
            {
                oleDbCommand = new OleDbCommand
                {
                    Connection = _oleDbConnection
                };
                needsTransaction = true;
            }
            oleDbCommand.CommandText = "INSERT INTO AdItem (AdItem) VALUES (?)";
            oleDbCommand.Parameters.Clear();
            oleDbCommand.Parameters.AddWithValue("AdItem", adItemName);
            OleDbTransaction oleDbTransaction = null;
            try
            {             
                if (needsTransaction)
                {
                    //If the OleDbCommand object is not supplied, then we'll need to create and assign the transaction object.
                    oleDbCommand.Connection = _oleDbConnection;
                    _oleDbConnection.Open();
                    oleDbTransaction = _oleDbConnection.BeginTransaction();
                    oleDbCommand.Transaction = oleDbTransaction;
                }                               
                if (oleDbCommand.ExecuteNonQuery() == 1)
                {
                    oleDbCommand.CommandText = "SELECT ID FROM AdItem WHERE AdItem.AdItem = ?";
                    oleDbCommand.Parameters.Clear();
                    oleDbCommand.Parameters.AddWithValue("AdItem", adItemName);
                    var reader = oleDbCommand.ExecuteReader();
                    //Get the ID of the new ad item.
                    while (reader != null && reader.Read())
                    {
                        int.TryParse(reader[0].ToString(), out adItemId);
                    }
                    reader?.Close();

                    if (adItemId != 0)
                    {
                        //All was successful.
                        oleDbTransaction?.Commit();
                    }
                    else
                    {
                        //
                        _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                            "Ad item \"" + adItemName + "\" was not found in the database; rolling back changes.");
                        oleDbTransaction?.Rollback();
                    }
                }
                else
                {
                    //Something failed but wasn't caught.
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Failed to add the ad item \"" + adItemName + "\" into the database.");
                    oleDbTransaction?.Rollback();
                }
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, e.Message);
                _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                    "Failed to insert ad item " + adItemName + " into the database.");
                oleDbTransaction?.Rollback();
            }
            finally
            {
                if (needsTransaction)
                {
                    _oleDbConnection.Close();
                }                
            }

            return adItemId;
        }

        /// <summary>
        /// Infrastructure for the DatabaseWriter class, not meant to be used with external code.
        /// Grabs the ID of the specified row.
        /// </summary>
        /// <param name="tableName">The name of the table to check for the row in.</param>
        /// <param name="adItemId">The ID of the ad item in the row.</param>
        /// <param name="dateId">The ID of the date in the row.</param>
        /// <returns>The ID of the row, zero(0) if no rows are found.</returns>
        private int RetrieveRowId(string tableName, int adItemId, int dateId)
        {
            var id = 0;
            var rowsEffected = 0;
            var oleDbCommand = new OleDbCommand
            {
                CommandText = "SELECT ID FROM " + tableName + " WHERE FK_AdItemID = ? AND FK_DateID = ?",
                Connection = _oleDbConnection
            };
            oleDbCommand.Parameters.AddWithValue("AdItemID", adItemId);
            oleDbCommand.Parameters.AddWithValue("DateID", dateId);

            try
            {
                _oleDbConnection.Open();
                var reader = oleDbCommand.ExecuteReader();
                while (reader != null && reader.Read())
                {
                    rowsEffected++;
                    int.TryParse(reader[0].ToString(), out id);
                }
                reader?.Close();

                if (rowsEffected > 1)
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                        "Redundancy found row with the ad item ID " + adItemId + " with the date ID " + dateId + ".");
                }
            }
            catch (OleDbException e)
            { 
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to look up the existence of a row with the ad item ID " + adItemId + " with the date ID " + dateId + ".");
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, e.Message);
            }
            _oleDbConnection.Close();
            return id;
        }
        #endregion

        //10 to 1 ratio of tries to code
        //http://codebetter.com/karlseguin/2006/04/05/understanding-and-using-exceptions/nfrastructure

        public bool InsertIntoWeekEnding(string dateString)
        {
            //Assume the INSERT operation failed in case anything other error arises.
            var insertWasSuccessful = false;
            //Set up the command object, SQL command string and parameters.
            var oleDbCommand = new OleDbCommand
            {
                CommandText = "INSERT INTO WeekEnding(EndOfWeekDate) VALUES ( dateString )"
            };
            oleDbCommand.Parameters.AddWithValue("dateString", dateString);
            oleDbCommand.Connection = _oleDbConnection;
            //Try to execute the query
            try
            {
                var numberOfRowsEffected = 0;
                //Check for the existence of the date string that was provided.
                oleDbCommand.CommandText = "SELECT ID FROM WeekEnding WHERE EndOfWeekDate = @dateString";
                oleDbCommand.Parameters.AddWithValue("@dateString", dateString);
                oleDbCommand.Connection = _oleDbConnection;
                _oleDbConnection.Open();
                //Execute the SELECT statement and retrieve the row(s) effected.
                var reader = oleDbCommand.ExecuteReader();
                var recordIndex = 0;
                while (reader != null && reader.Read())
                {
                    if (reader[recordIndex].ToString() != "")
                    {
                        numberOfRowsEffected++;
                    }
                    recordIndex++;
                }
                reader?.Close();
                //IF one row was affected, then return with "True", since the value is already there.
                if (numberOfRowsEffected == 1)
                {
                    //Success! Without even lifting a finger, how nice.
                    return true;
                }
                //ELSE IF more then one row was effected, then that means we have redundancy...
                else if (numberOfRowsEffected > 1)
                {
                    oleDbCommand.CommandText = "DELETE FROM WeekEnding WHERE EndOfWeekDate = @dateString";
                    oleDbCommand.Parameters.Clear();
                    oleDbCommand.Parameters.AddWithValue("@dateString", dateString);
                    numberOfRowsEffected = oleDbCommand.ExecuteNonQuery();
                    if (numberOfRowsEffected > 1)
                    {
                        //Deletion of extra dates has completed successfully so add in the provided date string.
                        oleDbCommand.CommandText = "INSERT INTO WeekEnding(EndOfWeekDate) VALUES(@dateString)";
                        oleDbCommand.Parameters.Clear();
                        oleDbCommand.Parameters.AddWithValue("@dateString", dateString);
                        numberOfRowsEffected = oleDbCommand.ExecuteNonQuery();
                        if (numberOfRowsEffected != 1)
                        {
                            //?
                            _logConsole.WriteToLog(FrmLogConsole.Level.Debug, "An error has occurred attempting to insert the date " + dateString + " into the week ending table.");
                        }
                    }
                }
                else if (numberOfRowsEffected == 0)
                {
                    oleDbCommand.CommandText = "INSERT INTO WeekEnding(EndOfWeekDate) VALUES (?)";
                    oleDbCommand.Parameters.Clear();
                    oleDbCommand.Parameters.AddWithValue("dateString", dateString);
                    numberOfRowsEffected = oleDbCommand.ExecuteNonQuery();
                    if (numberOfRowsEffected == 0)
                    {
                        //?
                        _logConsole.WriteToLog(FrmLogConsole.Level.Debug,
                            "An error has occurred attempting to insert the date " + dateString +
                            " into the week ending table.");
                    }
                    else
                    {
                        insertWasSuccessful = true;
                    }
                }
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "An error occurred trying to write a record to the Week Ending table.");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message + "\n" + e.StackTrace);
            }
            finally
            {
                //Make certain that the connection is closed before returning.
                _oleDbConnection.Close();
            }

            return insertWasSuccessful;
        }

        public bool RedundantlessInsertIntoComments(string comments, string dateIdString)
        {
            //Again, assume a failed operation so there are no false positives.
            var insertWasSuccessful = false;
            var storedComment = "";
            //Set up the command object, SQL command string and parameters.
            var oleDbCommand = new OleDbCommand {Connection = _oleDbConnection};
            //Try to execute the query
            try
            {
                int numberOfRowsEffected;

                //IF one row was affected, then check to see if the comments are the same.
                //Check to see if the comments already exist.
                //TODO: Perform a little Reg-ex magic to determine if the comments are just different due to spaces or small word changes.
                oleDbCommand.CommandText = "SELECT Comment FROM Comment WHERE FK_DateID = dateID";
                oleDbCommand.Parameters.Clear();
                oleDbCommand.Parameters.AddWithValue("dateID", dateIdString);
                _oleDbConnection.Open();
                //OpenConnection();
                var reader = oleDbCommand.ExecuteReader();
                var recordIndex = 0;
                while (reader != null && reader.Read())
                {
                    if (recordIndex == 0)
                    {
                        storedComment = reader[0].ToString();
                    }
                    else
                    {
                        storedComment += reader[0].ToString();
                    }
                    if (storedComment != "")
                    {
                        recordIndex++;
                    }
                }
                reader?.Close();
                //IF there is a comment that has the same date then check to see if it is the same as the one entered.
                if (recordIndex == 1)
                {
                    if (storedComment == comments)
                    {
                        //The comments match so return true.
                        return true;
                    }
                    else
                    {
                        //ELSE the comments are different, therefore the entry needs to be updated.
                        oleDbCommand.CommandText = "UPDATE Comment SET Comment.Comment = ? WHERE [Comment.FK_DateID] = ?;";
                        oleDbCommand.Parameters.Clear();
                        oleDbCommand.Parameters.AddWithValue("comment", storedComment + "\r\n" + comments);
                        oleDbCommand.Parameters.AddWithValue("dateID", dateIdString);
                        numberOfRowsEffected = oleDbCommand.ExecuteNonQuery();

                        if (numberOfRowsEffected == 1)
                        {
                            //Update was successful, so return true.
                            return true;
                        }
                        else
                        {
                            _logConsole.WriteToLog(FrmLogConsole.Level.Error, "An error has occurred trying to update a comment with the date ID of " + dateIdString + ".");
                            return false;
                        }        
                    }
                }
                else if (recordIndex > 1)
                {
                    //ELSE IF more then one record was found with the same date ID, then clear the redundancy and rewrite to the database.
                    numberOfRowsEffected = 0;
                    oleDbCommand.CommandText = "DELETE FROM Comment WHERE FK_DateID = dateID";
                    oleDbCommand.Parameters.Clear();
                    oleDbCommand.Parameters.AddWithValue("dateID", dateIdString);
                    numberOfRowsEffected = oleDbCommand.ExecuteNonQuery();
                    if (numberOfRowsEffected > 1)
                    {
                        oleDbCommand.CommandText = "INSERT INTO Comment(Comment, FK_DateID) VALUES(comments, dateID)";
                        oleDbCommand.Parameters.Clear();
                        oleDbCommand.Parameters.AddWithValue("comments", storedComment + "\r\n" + comments);
                        oleDbCommand.Parameters.AddWithValue("dateID", dateIdString);
                        numberOfRowsEffected = oleDbCommand.ExecuteNonQuery();
                        if (numberOfRowsEffected == 1)
                        {
                            return true;
                        }
                        else
                        {
                            _logConsole.WriteToLog(FrmLogConsole.Level.Debug, "An error occurred trying to insert a new comment after attempting to delete redundant entries.");
                            return false;
                        }
                    }
                    else
                    {
                        _logConsole.WriteToLog(FrmLogConsole.Level.Debug, "An error occurred trying to delete redundant comments.");
                        return false;
                    }
                }
                //Reset the number effected so there is no confusion.
                numberOfRowsEffected = 0;
                //Now execute the INSERT statement since no redundancy was found.
                //The comments are not found to be used in the database anywhere, nor the date ID so add a brand new row.
                oleDbCommand.CommandText = "INSERT INTO Comment(Comment, FK_DateID) VALUES (comments, dateID)";
                oleDbCommand.Parameters.Clear();
                oleDbCommand.Parameters.AddWithValue("comments", comments);
                oleDbCommand.Parameters.AddWithValue("dateID", dateIdString);
                numberOfRowsEffected = oleDbCommand.ExecuteNonQuery();

                if (numberOfRowsEffected == 1)
                {
                    insertWasSuccessful = true;
                }
                else if (numberOfRowsEffected == 0)
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to insert new comments into the Comment table.");
                    insertWasSuccessful = false;
                }
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "An error occurred trying to write a record to the Comment table.");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, "Message " + e.Message);
            }
            finally
            {
                //Make certain that the connection is closed before returning.
                _oleDbConnection.Close();
            }

            return insertWasSuccessful;
        }
        /// <summary>
        /// Inserts the data table provided into the APC table.
        /// The rows of the table must match the physical layout of the 
        /// APC table. The last column in the table, just before the foreign keys
        /// is RowAttribute and row position. Then its Fk_AdItem, FK_GroupID and FK_DateID (always the last foreign key).
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns>A list which contains the row numbers of all added rows.</returns>
        public List<int> RedundantlessInsertIntoApc(DataTable parameters)
        {
            //Check to see if the DataTable is empty, and if it is one return -1 as the error.
            if (parameters == null || parameters.Rows.Count == 0)
            {
                //Create new List<int> variable and assign it to 0.
                var noRowsAdded = new List<int> {0};
                return noRowsAdded;
            }
            _oleDbConnection.Open();
            var rowsAdded = new List<int>();
            var rowNumber = 0;
            //DataTable's structure will reflect the APC database table structure.
            foreach (DataRow row in parameters.Rows)
            {
                var adItemId = ReturnAdItemIdFromAdItemString(row[18].ToString());
                var dateId = row[20].ToString(); //The nineteenth (19th) entry is the dateID field.
                var rowsEffected = 0;

                if (adItemId == "0")
                {
                    //IF the ad item could not be found in the database, add it in.
                    adItemId = InsertAdItem(row[17].ToString());
                    //IF the ID is still zero (0), then something went wrong...
                    if (adItemId == "0")
                    {
                        //Add an error code to the end of the array; something went wrong adding the new item to the database.
                        rowsAdded.Add(0);
                        return rowsAdded;
                    }
                }

                if (!DoesEntryExist(adItemId, dateId))
                {
                    //IF the ad item isn't in the APC table with the specified date, then add it to the database.
                    var oleDbCommand = new OleDbCommand
                    {
                        CommandText =
                            "INSERT INTO APC(ProjectionSold, ProjectionSalePrice, ProjectionTotalSales, ProjectionCost, ProjectionProfitReturn, ProjectionTotalProfitReturn, BeginingInventory, Received, TotalInventory, EndingInventory, ActualSold, ActualSalePrice, ActualTotalSales, ActualCost, ActualProfitReturn, ActualTotalProfitReturn, RowAttribute, RowPosition, FK_AdItemID, FK_GroupID, FK_DateID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
                    };
                    oleDbCommand.Parameters.AddWithValue("prSold", row[0]);
                    oleDbCommand.Parameters.AddWithValue("prSalesPrice", row[1]);
                    oleDbCommand.Parameters.AddWithValue("prTotalSales", row[2]);
                    oleDbCommand.Parameters.AddWithValue("prCost", row[3]);
                    oleDbCommand.Parameters.AddWithValue("prProfitReturn", row[4]);
                    oleDbCommand.Parameters.AddWithValue("prTotalProfitReturn", row[5]);
                    oleDbCommand.Parameters.AddWithValue("beginingInv", row[6]);
                    oleDbCommand.Parameters.AddWithValue("receivedInv", row[7]);
                    oleDbCommand.Parameters.AddWithValue("totalInv", row[8]);
                    oleDbCommand.Parameters.AddWithValue("endingInv", row[9]);
                    oleDbCommand.Parameters.AddWithValue("acSold", row[10]);
                    oleDbCommand.Parameters.AddWithValue("acSalesPrice", row[11]);
                    oleDbCommand.Parameters.AddWithValue("acTotalSales", row[12]);
                    oleDbCommand.Parameters.AddWithValue("acCost", row[13]);
                    oleDbCommand.Parameters.AddWithValue("acProfitReturn", row[14]);
                    oleDbCommand.Parameters.AddWithValue("acTotalProfitReturn", row[15]);
                    oleDbCommand.Parameters.AddWithValue("RowAttribute", row[16]);
                    oleDbCommand.Parameters.AddWithValue("RowPosition", row[17]);
                    oleDbCommand.Parameters.AddWithValue("AdItemID", adItemId);
                    oleDbCommand.Parameters.AddWithValue("GroupID", row[19]);
                    oleDbCommand.Parameters.AddWithValue("dateID", row[20]);
                    oleDbCommand.Connection = _oleDbConnection;

                    try
                    {
                        var reader = oleDbCommand.ExecuteReader();
                        while (reader != null && reader.Read())
                        {
                            rowsEffected++;
                        }
                        reader?.Close();
                        if (rowsEffected == 1)
                        {
                            rowsAdded.Add(rowNumber);             
                        }
                    }
                    catch (OleDbException e)
                    {
                        _logConsole.WriteToLog(FrmLogConsole.Level.Error, "An error occurred trying to write a record to the APC table.");
                        _logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message);
                        _oleDbConnection.Close();
                        //Add an error code at the end of array of rows that were added to show an error occurred.
                        rowsAdded.Add(-1);
                        return rowsAdded;
                    }
                }
                else
                {
                    //Perform an update operation on the row in question.
                    if (!UpdateRow(adItemId, dateId, row))
                    {
                        //IF the update fails, then return with an error appended to the end of the array.
                        rowsAdded.Add(0);
                        _logConsole.WriteToLog(FrmLogConsole.Level.Error, "An error occurred trying to update a record APC table.");
                        _logConsole.WriteToLog(FrmLogConsole.Level.Debug, "An error occurred trying to update ad item ID " + adItemId + " and dateID " + dateId + ".");
                        _oleDbConnection.Close();
                        return rowsAdded;
                    }
                }
                rowNumber++;
            }

            //Close the database connection before returning.
            _oleDbConnection.Close();
            return rowsAdded;
        }

        /// <summary>
        /// Infrastructure for the DatabaseWriter class, not meant to be used with external code; expects an open connection when called.
        /// Checks to see if an ad item exists based on its end of week date.
        /// </summary>
        /// <param name="adItemId">The ID of the item.</param>
        /// <param name="dateId">The ID of the end of week date.</param>
        /// <returns>True if the item exists, or false if it doesn't.</returns>
        private bool DoesEntryExist(string adItemId, string dateId)
        {
            var exists = false;
            var oleDbCommand = new OleDbCommand();
            var rowsEffected = 0;
            oleDbCommand.CommandText = "SELECT ID FROM APC WHERE FK_AdItemID = adItemID AND FK_DateID = dateID";
            oleDbCommand.Parameters.AddWithValue("adItemID", adItemId);
            oleDbCommand.Parameters.AddWithValue("dateID", dateId);
            oleDbCommand.Connection = _oleDbConnection;
            try
            {
                oleDbCommand.Transaction = _oleDbConnection.BeginTransaction();
                var reader = oleDbCommand.ExecuteReader();
                while (reader != null && reader.Read())
                {
                    rowsEffected++;
                }
                reader?.Close();
            }
            catch (OleDbException ex)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "An error occurred trying to check for the existence of an ad item with the ID of " + adItemId + ".");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, ex.Message);
            }

            if (rowsEffected == 1)
            {
                exists = true;
            }
            else if (rowsEffected > 1)
            {
                //Throw custom exception, or add a function to correct this issue.
                _logConsole.WriteToLog(FrmLogConsole.Level.Critical, "A redundant entry has been found with the following values: AdItemID " + adItemId + " and DateID " + dateId + ".");
                exists = true;
            }

            return exists;
        }

        /// <summary>
        /// Infrastructure for the DatabaseWriter class, not meant to be used with external code; expects an open connection when called.
        /// This method adds a specified ad item to the database's ad item table.
        /// </summary>
        /// <param name="adItemName">The name of the ad item.</param>
        /// <returns>The ID number of the ad item, or zero (0) on fail.</returns>
        private string InsertAdItem(string adItemName)
        {
            //Remove all nulls from the adItemName and check if it is null.
            string cleanedAdItemName = adItemName.Replace(" ", "");
            if (adItemName == "")
            {
                //
                //throw new System.ArgumentException("Attempted to insert a null ad item name into the database.");
                return "0";
            }
            else if (cleanedAdItemName.Length == 1)
            {
                //
                //throw new System.ArgumentException("Attempted to insert an ad item name with invalid length.");
                return "0";
            }
            //Record the number of rows affected when the statement is executed, again assume nothing was affected.
            var adItemId = "0";
            var oleDbCommand = new OleDbCommand
            {
                CommandText = "INSERT INTO AdItem (AdItem) VALUES (?)",
                Connection = _oleDbConnection
            };
            oleDbCommand.Parameters.AddWithValue("adItem", adItemName);
            //Attempt to execute the INSERT SQL statement.
            try
            {
                var rowsEffected = oleDbCommand.ExecuteNonQuery();

                //IF one (1) row was affected, then get the ad item's ID and set it to the return value.
                if (rowsEffected == 1)
                {
                    //Modify the OleDbCommand object to query the ad item with the highest ID value since that would be the most recent item added.
                    oleDbCommand.CommandText = "SELECT ID FROM AdItem WHERE ID = (SELECT MAX(AdItem.ID) FROM AdItem)";
                    var reader = oleDbCommand.ExecuteReader();
                    while (reader != null && reader.Read())
                    {
                        adItemId = reader[0].ToString();
                    }
                    reader?.Close();
                }
                //ELSE IF more then one (1) row was affected...
                else if (rowsEffected > 1)
                {
                    //?
                }
                //ELSE IF no rows are effected due to an uncaught exception, log it.
                else if (rowsEffected == 0)
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Critical, "Failed to add " + adItemName + " into the database; zero (0) rows affected.");
                    return "0";
                }
            }
            catch (OleDbException ex)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "An error occurred trying to add " + adItemName + " to the database.");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, ex.Message);
            }
            return adItemId;
        }

        /// <summary>
        /// Infrastructure for the DatabaseWriter class, not meant to be used with external code; expects an open connection when called.
        /// Returns the ad item ID from the ad item's name.
        /// </summary>
        /// <returns>The ID of the specified item.</returns>
        private string ReturnAdItemIdFromAdItemString(string adItemName)
        {
            var id = "0";
            double parsedName;
            //Clear all invalid characters and check if its a null entry.
            if (adItemName.Replace(" " , "") == "")
            {
                return id;
            }
            if (double.TryParse(adItemName, out parsedName))
            {
                //A number has been found so error out.
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Ad item name cannot be only numeric characters.");
                return id;
            }
            var oleDbCommand = new OleDbCommand {CommandText = "SELECT ID FROM AdItem WHERE UCASE(AdItem.AdItem) = UCASE(adItemName)"};
            oleDbCommand.Parameters.AddWithValue("adItemName", adItemName);
            oleDbCommand.Connection = _oleDbConnection;

            try
            {
                var adItemId = ""; 
                var reader = oleDbCommand.ExecuteReader();

                while (reader != null && reader.Read())
                {
                    adItemId = reader[0].ToString();
                }
                if (reader != null) reader.Close();
                //Grab the ad item's ID.
                if (adItemId != "0")
                {
                    id = adItemId;
                }
                else
                {
                    //Return 0 as the ad item doesn't exist.
                    return id;
                }
            }
            catch (OleDbException ex)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "An error occurred trying to obtain the ad item ID for " + adItemName + ".");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, ex.Message);
            }

            return id;
        }

        /// <summary>
        /// Infrastructure for the DatabaseWriter class, not meant to be used with external code; expects an open connection when called.
        /// Performs an update operation on the row with matching IDs in the ad item and date ID columns.
        /// This is to be called when an ad item already exists and simply needs updating with new values.
        /// </summary>
        /// <param name="adItemId"></param>
        /// <param name="dateId"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private bool UpdateRow(string adItemId, string dateId, DataRow parameters)
        {
            var updateSuccessful = false;
            var oleDbCommand = new OleDbCommand
            {
                CommandText =
                    "UPDATE APC SET ProjectionSold = ?, ProjectionSalePrice = ?, ProjectionTotalSales = ?, ProjectionCost = ?, ProjectionProfitReturn = ?, ProjectionTotalProfitReturn = ?, BeginingInventory = ?, Received = ?, TotalInventory = ?, EndingInventory = ?, ActualSold = ?, ActualSalePrice = ?, ActualTotalSales = ?, ActualCost = ?, ActualProfitReturn = ?, ActualTotalProfitReturn = ?, RowAttribute = ?, RowPosition = ?, FK_GroupID = ? WHERE FK_DateID = ? AND FK_AdItemID = ?"
            };
            oleDbCommand.Parameters.AddWithValue("prSold", parameters[0]);
            oleDbCommand.Parameters.AddWithValue("prSalesPrice", parameters[1]);
            oleDbCommand.Parameters.AddWithValue("prTotalSales", parameters[2]);
            oleDbCommand.Parameters.AddWithValue("prCost", parameters[3]);
            oleDbCommand.Parameters.AddWithValue("prProfitReturn", parameters[4]);
            oleDbCommand.Parameters.AddWithValue("prTotalProfitReturn", parameters[5]);
            oleDbCommand.Parameters.AddWithValue("beginingInv", parameters[6]);
            oleDbCommand.Parameters.AddWithValue("receivedInv", parameters[7]);
            oleDbCommand.Parameters.AddWithValue("totalInv", parameters[8]);
            oleDbCommand.Parameters.AddWithValue("endingInv", parameters[9]);
            oleDbCommand.Parameters.AddWithValue("acSold", parameters[10]);
            oleDbCommand.Parameters.AddWithValue("acSalesPrice", parameters[11]);
            oleDbCommand.Parameters.AddWithValue("acTotalSales", parameters[12]);
            oleDbCommand.Parameters.AddWithValue("acCost", parameters[13]);
            oleDbCommand.Parameters.AddWithValue("acProfitReturn", parameters[14]);
            oleDbCommand.Parameters.AddWithValue("acTotalProfitReturn", parameters[15]);
            oleDbCommand.Parameters.AddWithValue("RowAttribute", parameters[16]);
            oleDbCommand.Parameters.AddWithValue("RowPosition", parameters[17]);
            oleDbCommand.Parameters.AddWithValue("groupID", parameters[19]);
            oleDbCommand.Parameters.AddWithValue("dateID", parameters[20]);
            oleDbCommand.Parameters.AddWithValue("adItemID", adItemId);
            oleDbCommand.Connection = _oleDbConnection;

            try
            {
                var numberOfRowsEffected = oleDbCommand.ExecuteNonQuery();
                if (numberOfRowsEffected == 1)
                {
                    updateSuccessful = true;
                }
                else if (numberOfRowsEffected > 1) //?
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Warning, "Redundancy found: Ad item ID " + parameters[0] + " (" + parameters[17] + ") and date ID " + parameters[18] + ".");
                    updateSuccessful = true;
                }
                _logConsole.WriteToLog(FrmLogConsole.Level.Info, "Affected " + numberOfRowsEffected + " updating the ad item " + parameters[17] + ".");
            }
            catch (OleDbException ex)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to update ad item with the ID of " + parameters[0] + " (" + parameters[17] + ") and a date ID of " + parameters[18] + ".");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, ex.Message);
                return false;
            }

            return updateSuccessful;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="parameters">A copy of the Supplier DataGridView table.</param>
        /// <returns></returns>
        public List<int> RedundantlessInsertIntoInvoice(DataTable parameters)
        {
            //Create an array that hold the indexes of all the rows that were successfully written to the database.
            var rowsAdded = new List<int>();
            var supplierId = "";
            //Setup object for each of the three (3) tasks that need to be performed.
            //Checking for the ID of a particular supplier, by name.
            var supplierQueryCommand = new OleDbCommand
            {
                CommandText = "SELECT ID FROM Supplier WHERE SupplierName = ?",
                Connection = _oleDbConnection
            };
            //Grabbing the ID of the invoice by the invoice number and the supplier's ID.
            var invoiceCheckCommand = new OleDbCommand
            {
                CommandText = "SELECT ID FROM Invoice WHERE InvoiceNumber = ? AND FK_Supplier = ?",
                Connection = _oleDbConnection
            };
            //Inserting a new record into the Invoice table.
            var insertNewInvoice = new OleDbCommand
            {
                CommandText =
                    "INSERT INTO Invoice (InvoiceDate, InvoiceNumber, InvoiceNetAmountAtCost, InvoiceNetAmount, InvoiceNote, FK_Supplier, FK_DateID) VALUES (?, ?, ?, ?, ?, ?, ?)",
                Connection = _oleDbConnection
            };
            _oleDbConnection.Open();
            foreach (DataRow row in parameters.Rows)
            {
                var itemCount = 0;
                var index = 0;
                foreach (var obj in row.ItemArray)
                {
                    //Check for null objects, row size is 8 on creation for some reason.
                    if (index < 7)
                    {
                        if ((string)obj != "")
                        {
                            itemCount++;
                        }
                        else
                        {
                            row[index] = 0;
                        }
                    }
                    index++;
                }

                if (itemCount < 2)
                {
                    break;
                }

                var recordCount = 0;
                try
                {
                    //Check for the existence of the supplier to be written.
                    supplierQueryCommand.Parameters.Clear();
                    supplierQueryCommand.Parameters.AddWithValue("SupplierName", row[1]);
                    var reader = supplierQueryCommand.ExecuteReader();
                    //Read in the value(s) from the database.
                    while (reader != null && reader.Read())
                    {
                        if (recordCount == 0)
                        {
                            supplierId = reader[0].ToString();
                        }
                        recordCount++;
                    }
                    if(reader != null) reader.Close();

                    //IF no records were pulled, then ad the supplier's name into the database and pull the ID for the new entry.
                    if (recordCount == 0)
                    {
                        supplierId = InsertSupplier(row[1].ToString());

                        if (supplierId != "0")
                        {
                            recordCount = 1;
                        }
                        //ELSE IF the supplier ID wasn't set, indicting an error, so break out of the loop and add zero (0) to the end of the rows effected array.
                        else
                        {
                            rowsAdded.Add(0);
                            break;
                        }

                    }
                    //IF the supplier exists in the database, then check for the presence of the supplier and the supplied invoice number.
                    if (recordCount == 1)
                    {
                        invoiceCheckCommand.Parameters.Clear();
                        invoiceCheckCommand.Parameters.AddWithValue("InvoiceNumber", row[2]);
                        invoiceCheckCommand.Parameters.AddWithValue("SupplierID", supplierId);
                        reader = invoiceCheckCommand.ExecuteReader();
                        recordCount = 0;

                        while (reader != null && reader.Read())
                        {
                            recordCount++;
                        }
                        if (reader != null) reader.Close();

                        //IF the entry does exist, then update it with the new information provided.
                        if (recordCount == 1)
                        {
                            //Call the update function and attempt to update the information.
                            if (!UpdateInvoice(row, supplierId))
                            {
                                //IF the update failed log the failure, add in a failure at the row that failed, and break out.
                                //LOGGING GOES HERE
                                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to update the record for " + row[1] + ".");
                                rowsAdded.Add(0);
                                break;
                            }
                        }
                        else if (recordCount > 1)
                        {
                            //TODO: Clean up the database's redundant entries.
                        }
                        else if (recordCount == 0)
                        {
                            //ELSE IF no records were found, then insert the new invoice into the Invoice table.
                            insertNewInvoice.Parameters.Clear();
                            insertNewInvoice.Parameters.AddWithValue("InvoiceDate", row[0]);
                            insertNewInvoice.Parameters.AddWithValue("InvoiceNumber", row[2]);
                            insertNewInvoice.Parameters.AddWithValue("InvoiceNetAmountAtCost", row[3]);
                            insertNewInvoice.Parameters.AddWithValue("InvoiceNetAmount", row[4]);
                            insertNewInvoice.Parameters.AddWithValue("InvoiceNote", row[5]);
                            insertNewInvoice.Parameters.AddWithValue("SupplierID", supplierId);
                            insertNewInvoice.Parameters.AddWithValue("DateID", row[6]);

                            var rowsEffected = insertNewInvoice.ExecuteNonQuery();

                            if (rowsEffected == 1) continue;
                            _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to write new invoice to the database for supplier " + row[1] + " ID of " + supplierId + ".");
                            rowsAdded.Add(0);
                            break;
                        }
                    }
                    //ELSE IF more then one record was found, clean up the redundancy.
                    else if (recordCount > 1)
                    {
                        _logConsole.WriteToLog(FrmLogConsole.Level.Info, "Redundancy found in the invoices table with supplier " + row[1] + ".");
                    }
                }
                catch (OleDbException e)
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to write supplier " + row[1] + " into the invoice table.");
                    _logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message);
                    _oleDbConnection.Close();
                    break;
                }
            }

            _oleDbConnection.Close();
            return rowsAdded;
        }
        /// <summary>
        /// Infrastructure for the DatabaseWriter class, not meant to be used with external code; expects an open connection when called.
        /// 
        /// </summary>
        /// <param name="supplierName"></param>
        /// <returns></returns>
        private string InsertSupplier(string supplierName)
        {
            double doubleParsedValue;
            if (supplierName == "")
            {
                return "0";
            }

            if(double.TryParse(supplierName, out doubleParsedValue))
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Supplier name cannot be only numeric characters.");
                return "0";
            }

            var supplierNameId = "0";
            var oleDbCommand = new OleDbCommand {CommandText = "INSERT INTO Supplier (SupplierName) VALUES (?)"};
            oleDbCommand.Parameters.AddWithValue("SupplierName", supplierName);
            oleDbCommand.Connection = _oleDbConnection;

            try
            {
                var rowsEffected = oleDbCommand.ExecuteNonQuery();

                if (rowsEffected == 1)
                {
                    oleDbCommand.CommandText = "SELECT ID FROM Supplier WHERE ID = (SELECT MAX(Supplier.ID) FROM Supplier)";
                    var reader = oleDbCommand.ExecuteReader();

                    while (reader != null && reader.Read())
                    {
                        supplierNameId = reader[0].ToString();
                    }

                    if (reader != null) reader.Close();
                }
                else if (rowsEffected > 1)
                {
                    //TODO: Clean up the database.
                }
                else
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Critical, "Failed to write supplier name " + supplierName + " to the suppliers table.");
                }
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Critical, "Failed to write supplier name " + supplierName + ".");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message);
            }

            return supplierNameId;
        }

        /// <summary>
        /// Infrastructure for the DatabaseWriter class, not meant to be used with external code; expects an open connection when called.
        /// 
        /// </summary>
        /// <param name="invoiceField"></param>
        /// <param name="supplierId"></param>
        /// <returns></returns>
        private bool UpdateInvoice(DataRow invoiceField, string supplierId)
        {
            var updateSuccessful = false;
            var oleDbCommand = new OleDbCommand
            {
                CommandText =
                    "UPDATE Invoice SET InvoiceDate = ?, InvoiceNetAmountAtCost = ?, InvoiceNetAmount = ?, InvoiceNote = ? WHERE InvoiceNumber = ? AND FK_Supplier = ? AND FK_DateID = ?"
            };
            oleDbCommand.Parameters.AddWithValue("InvoiceDate", invoiceField[0]);
            oleDbCommand.Parameters.AddWithValue("InvoiceNetAmountAtCost", invoiceField[3]);
            oleDbCommand.Parameters.AddWithValue("InvoiceNetAmount", invoiceField[4]);
            oleDbCommand.Parameters.AddWithValue("InvoiceNote", invoiceField[5]);
            oleDbCommand.Parameters.AddWithValue("InvoiceNumber", invoiceField[2]);
            oleDbCommand.Parameters.AddWithValue("SupplierID", supplierId);
            oleDbCommand.Parameters.AddWithValue("DateID", invoiceField[6]);
            oleDbCommand.Connection = _oleDbConnection;

            try
            {
                var rowsEffected = oleDbCommand.ExecuteNonQuery();

                if (rowsEffected == 1)
                {
                    updateSuccessful = true;
                }
                else
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to update record with invoice number " + invoiceField[2] + " for " + invoiceField[1] + ".");
                }
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to update invoice record invoice number " + invoiceField[2] + " for supplier " + invoiceField[1] + ".");
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, e.Message);
            }

            return updateSuccessful;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public int RedundantlessInsertIntoWeeklySales(DataRow parameters)
        {
            var rowsEffected = 0;
            var recordsRead = 0;
            //Object to check for the presence of an entry with the supplied date.
            var weekEndingDateCheck = new OleDbCommand
            {
                CommandText = "SELECT ID FROM WeeklySales WHERE FK_DateID = ?"
            };
            weekEndingDateCheck.Parameters.AddWithValue("DateID", parameters[8]);
            weekEndingDateCheck.Connection = _oleDbConnection;
            //Object to update a field with the date supplied, assuming an entry was found with the previous object.
            var updateWeeklySales = new OleDbCommand
            {
                CommandText =
                    "UPDATE WeeklySales SET Sunday = ?, Monday = ?, Tuesday = ?, Wednesday = ?, Thursday = ?, Friday = ?, Saturday = ?, TotalSales = ? WHERE FK_DateID = ?"
            };
            updateWeeklySales.Parameters.AddWithValue("Sunday", parameters[0]);
            updateWeeklySales.Parameters.AddWithValue("Monday", parameters[1]);
            updateWeeklySales.Parameters.AddWithValue("Tuesday", parameters[2]);
            updateWeeklySales.Parameters.AddWithValue("Wednesday", parameters[3]);
            updateWeeklySales.Parameters.AddWithValue("Thursday", parameters[4]);
            updateWeeklySales.Parameters.AddWithValue("Friday", parameters[5]);
            updateWeeklySales.Parameters.AddWithValue("Saturday", parameters[6]);
            updateWeeklySales.Parameters.AddWithValue("TotalSales", parameters[7]);
            updateWeeklySales.Parameters.AddWithValue("DateID", parameters[8]);
            updateWeeklySales.Connection = _oleDbConnection;
            //Object to insert a new field into the database if no entry is present.
            var insertWeeklySales = new OleDbCommand
            {
                CommandText =
                    "INSERT INTO WeeklySales (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, TotalSales, FK_DateID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
            };
            insertWeeklySales.Parameters.AddWithValue("Sunday", parameters[0]);
            insertWeeklySales.Parameters.AddWithValue("Monday", parameters[1]);
            insertWeeklySales.Parameters.AddWithValue("Tuesday", parameters[2]);
            insertWeeklySales.Parameters.AddWithValue("Wednesday", parameters[3]);
            insertWeeklySales.Parameters.AddWithValue("Thursday", parameters[4]);
            insertWeeklySales.Parameters.AddWithValue("Friday", parameters[5]);
            insertWeeklySales.Parameters.AddWithValue("Saturday", parameters[6]);
            insertWeeklySales.Parameters.AddWithValue("TotalSales", parameters[7]);
            insertWeeklySales.Parameters.AddWithValue("DateID", parameters[8]);
            insertWeeklySales.Connection = _oleDbConnection;
            try
            {
                _oleDbConnection.Open();
                //Execute the select statement to check for the presence of an entry with the supplied date (parameters[8]).
                var reader = weekEndingDateCheck.ExecuteReader();

                while (reader != null && reader.Read())
                {
                    recordsRead++;
                }
                if (reader != null) reader.Close();
                //IF there are no records with the date ID then add the current sales into the database.
                if (recordsRead == 0)
                {
                    rowsEffected = insertWeeklySales.ExecuteNonQuery();
                }
                //ELSE IF one already exists, then update it with the information provided.
                else if (recordsRead == 1)
                {
                    rowsEffected = updateWeeklySales.ExecuteNonQuery();
                }
                //ELSE IF more then one entry is detected, remove all redundant entries and insert the current sales into the database.
                else if (recordsRead > 1)
                {
                    //TODO: clean up the redundant entries.
                }
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                    "An error has occurred trying to write the weekly sales to the database.");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message);
            }
            finally
            {
               _oleDbConnection.Close();  
            }

            return rowsEffected;
        }

        public int RedundantlessInsertIntoGroupCategory(string groupName)
        {
            //
            var rowsEffected = 0;
            //Setup an object to check for the existence of the group name to be added.
            var categoryDescCheckQueryCommand = new OleDbCommand
            {
                CommandText = "SELECT ID FROM GroupCategory WHERE GroupDescription = ?"
            };
            categoryDescCheckQueryCommand.Parameters.AddWithValue("GroupName", groupName);
            categoryDescCheckQueryCommand.Connection = _oleDbConnection;
            //Setting up an object to insert a new ad special keyword.
            var insertNewCategoryDesc = new OleDbCommand
            {
                CommandText = "INSERT INTO GroupCategory (GroupDescription) VALUES (?)"
            };
            insertNewCategoryDesc.Parameters.AddWithValue("GroupName", groupName);
            insertNewCategoryDesc.Connection = _oleDbConnection;

            try
            {
                _oleDbConnection.Open();
                var reader = categoryDescCheckQueryCommand.ExecuteReader();

                while (reader != null && reader.Read())
                {
                    rowsEffected++;
                }
                if (reader != null) reader.Close();

                if (rowsEffected == 0)
                {
                    rowsEffected = insertNewCategoryDesc.ExecuteNonQuery();
                    if (rowsEffected == 0)
                    {
                        _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                            "An error has occurred trying to insert " + groupName + " into the database.");
                    }
                }
            }
            catch (OleDbException ex)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error,
    "An error has occurred trying to write a new ad special key word to the database.");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, ex.Message);
            }
            finally
            {
                _oleDbConnection.Close();
            }

            return rowsEffected;
        }

        public int RemoveAdSpecialMember(string adSpecialName)
        {
            var rowsEffected = 0;
            var oleDbCommand = new OleDbCommand()
            {
                CommandText = "DELETE FROM GroupCategory WHERE GroupDescription = ?"
            };
            oleDbCommand.Parameters.AddWithValue("AdSpecialName", adSpecialName);
            oleDbCommand.Connection = _oleDbConnection;

            try
            {
                _oleDbConnection.Open();
                rowsEffected = oleDbCommand.ExecuteNonQuery();
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error,
                    "Failed to delete the ad special " + adSpecialName + " from the database.");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message);
            }
            finally
            {
                _oleDbConnection.Close();
            }

            return rowsEffected;
        }

        public int RemoveRecord(string adItemId, string dateId)
        {
            var recordsDeleted = 0;
            var deleteCommand = new OleDbCommand
            {
                CommandText = "DELETE FROM APC WHERE FK_AdItemID = ? AND FK_DateID = ?"
            };
            deleteCommand.Parameters.AddWithValue("AdItemID", adItemId);
            deleteCommand.Parameters.AddWithValue("DateID", dateId);
            deleteCommand.Connection = _oleDbConnection;

            try
            {
                _oleDbConnection.Open();
                recordsDeleted = deleteCommand.ExecuteNonQuery();
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to delete the record with an ad item ID of " + adItemId + " and a date ID of " + dateId + ".");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message);
            }
            finally
            {
                _oleDbConnection.Close();
            }

            return recordsDeleted;
        }

        public int RemoveInvoice(string invoiceNumber, string dateId)
        {
            var recordsAffected = 0;
            var oleDbCommand = new OleDbCommand()
            {
                CommandText = "DELETE FROM Invoice WHERE InvoiceNumber = ? AND FK_DateID = ?"
            };
            oleDbCommand.Parameters.AddWithValue("InvoiceNumber", invoiceNumber);
            oleDbCommand.Parameters.AddWithValue("DateID", dateId);
            oleDbCommand.Connection = _oleDbConnection;

            try
            {
                _oleDbConnection.Open();
                recordsAffected = oleDbCommand.ExecuteNonQuery();
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to delete invoice number " + invoiceNumber + " with the date ID of " + dateId + ".");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message);
            }
            finally
            {
                _oleDbConnection.Close();
            }

            return recordsAffected;
        }

        /// <summary>
        /// Removes all records by the date ID passed in, and also removes
        /// the year's entry from the WeekEnding table.
        /// </summary>
        /// <param name="dateId">The ID of the date to be purged.</param>
        /// <returns>The number of records cleared from the database.</returns>
        public int RemoveAllEntriesAndYearById(string dateId)
        {
            var recordsRemoved = 0;
            //Object to clear the APC records associated with the date ID.
            var clearApCommand = new OleDbCommand()
            {
                CommandText = "DELETE FROM APC WHERE FK_DateID = ?"
            };
            clearApCommand.Parameters.AddWithValue("DateID", dateId);
            clearApCommand.Connection = _oleDbConnection;
            //Object to clear comments associated with the date ID.
            var clearCommentsCommand = new OleDbCommand()
            {
                CommandText = "DELETE FROM Comment WHERE FK_DateID = ?"
            };
            clearCommentsCommand.Parameters.AddWithValue("DateID", dateId);
            clearCommentsCommand.Connection = _oleDbConnection;
            //Object to clear the invoices associated with the date ID.
            var clearInvoicesCommand = new OleDbCommand()
            {
                CommandText = "DELETE FROM Invoice WHERE FK_DateID = ?"
            };
            clearInvoicesCommand.Parameters.AddWithValue("DateID", dateId);
            clearInvoicesCommand.Connection = _oleDbConnection;
            //Object to clear the weekly sales associated with the date ID.
            var clearWeeklySalesCommand = new OleDbCommand()
            {
                CommandText = "DELETE FROM WeeklySales WHERE FK_DateID = ?"
            };
            clearWeeklySalesCommand.Parameters.AddWithValue("DateID", dateId);
            clearWeeklySalesCommand.Connection = _oleDbConnection;
            //Object to clear the date associated with the ID passed in.
            var clearEndOfWeekDateCommand = new OleDbCommand()
            {
                CommandText = "DELETE FROM WeekEnding WHERE ID = ?"
            };
            clearEndOfWeekDateCommand.Parameters.AddWithValue("DateID", dateId);
            clearEndOfWeekDateCommand.Connection = _oleDbConnection;

            try
            {
                _oleDbConnection.Open();
                recordsRemoved += clearApCommand.ExecuteNonQuery();
                recordsRemoved += clearCommentsCommand.ExecuteNonQuery();
                recordsRemoved += clearInvoicesCommand.ExecuteNonQuery();
                recordsRemoved += clearWeeklySalesCommand.ExecuteNonQuery();
                recordsRemoved += clearEndOfWeekDateCommand.ExecuteNonQuery();
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "And error has occurred attempting to delete all records associated with the date ID of " + dateId + ".");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message);
            }
            finally
            {
                _oleDbConnection.Close();
            }
            return recordsRemoved;
        }

        /// <summary>
        /// Updates the comments stored in a particular date.
        /// TODO: Fix this bug...
        /// IF the delete command deletes more then one row it returns 0.
        /// </summary>
        /// <param name="comment"></param>
        /// <param name="dateId"></param>
        /// <returns>Returns true if the row is deleted and false if a row fails to be deleted.</returns>
        public bool UpdateCommentsByDateId(string comment, string dateId)
        {
            var wasSuccessful = false;
            var oleDbCommand = new OleDbCommand()
            {
                CommandText = "UPDATE Comment SET Comment.Comment = ? WHERE  FK_DateID = ?"
            };
            oleDbCommand.Parameters.AddWithValue("Comment", comment);
            oleDbCommand.Parameters.AddWithValue("DateID", dateId);
            oleDbCommand.Connection = _oleDbConnection;

            try
            {
                //IF the delete command deletes more then one row it returns 0.
                _oleDbConnection.Open();
                var recordsEffected = oleDbCommand.ExecuteNonQuery();
                if (recordsEffected == 1)
                {
                    wasSuccessful = true;
                }
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "And error has occurred attempting to update the comments for the date ID of " + dateId + ".");
                _logConsole.WriteToLog(FrmLogConsole.Level.Debug, e.Message);
            }
            finally
            {
                _oleDbConnection.Close();
            }

            return wasSuccessful;
        }

        public bool RemoveAdItem(string adItemName)
        {
            var success = false;
            var oleDbCommand = new OleDbCommand
            {
                CommandText = "DELETE FROM AdItem WHERE AdItem = ?"
            };
            oleDbCommand.Parameters.AddWithValue("AdItemName", adItemName);
            oleDbCommand.Connection = _oleDbConnection;

            try
            {
                _oleDbConnection.Open();
                var rowsEffected = oleDbCommand.ExecuteNonQuery();

                if(rowsEffected == 1)
                {
                    success = true;
                }
                else if(rowsEffected > 1)
                {
                    _logConsole.WriteToLog(FrmLogConsole.Level.Info, "Removed redundant entry " + adItemName + " from the database successfully.");
                    success = true;
                }
                else
                {

                }
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to delete the ad item " + adItemName + " from the database.");
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, e.Message);
            }
            finally
            {
                _oleDbConnection.Close();
            }

            return success;
        }

        public bool AddNewItem(string adItemName)
        {
            var success = false;
            var oleDbCommand = new OleDbCommand
            {
                CommandText = "INSERT INTO AdItem (AdItem) VALUES (?)"
            };
            oleDbCommand.Parameters.AddWithValue("AdItemName", adItemName);
            oleDbCommand.Connection = _oleDbConnection;
            var redundantancyCheck = new OleDbCommand
            {
                CommandText = "SELECT AdItem FROM AdItem WHERE AdItem = ?"
            };
            redundantancyCheck.Parameters.AddWithValue("AdItemName", adItemName);
            redundantancyCheck.Connection = _oleDbConnection;

            try
            {
                _oleDbConnection.Open();
                using(var reader = redundantancyCheck.ExecuteReader())
                {
                    var rows = 0;
                    while(reader != null && reader.Read())
                    {
                        rows++;
                    }
                    if(rows == 0)
                    {
                        var rowsEffected = oleDbCommand.ExecuteNonQuery();
                        if (rowsEffected == 1)
                        {
                            success = true;
                        }
                        else
                        {
                            _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to insert new ad item " + adItemName + ".");
                        }
                    }
                    else
                    {
                        success = true;
                        _logConsole.WriteToLog(FrmLogConsole.Level.Debug, "Ad Item " + adItemName + " found with " + rows + " row(s).");
                    }
                }
            }
            catch (OleDbException e)
            {
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, "Failed to add the new ad item " + adItemName + " to the database.");
                _logConsole.WriteToLog(FrmLogConsole.Level.Error, e.Message);
            }
            finally
            {
                _oleDbConnection.Close();
            }

            return success;
        }
    }
}
