using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;

namespace AdvertsingProfitControl
{
    public partial class NewAddRecord : Form
    {
        private static readonly FrmLogConsole LogConsole = FrmLogConsole.GetStaticInstance;

        public NewAddRecord()
        {
            InitializeComponent();
            //Assign the events that all APC DataGridViews will use.
            projectionsDataGridView.RowsAdded += DisplayRowNumbers;
            inventoryDataGridView.RowsAdded += DisplayRowNumbers;
            actualDataGridView.RowsAdded += DisplayRowNumbers;

            //Assign the events for the comments text box and display the remaining character count for the user.
            commentsTextBox.TextChanged += DisplayRemainingCommentCharacterCount;
            //commentsTextBox.KeyUp += DisplayRemainingCommentCharacterCount;
            commentsGroupBox.Text = @"Comments (Characters Remaining: " + commentsTextBox.MaxLength + @")";

            /*
             * 
    OnCellLeave(C1)
    OnRowLeave(R1)
    OnCellValidating(C1)
    OnCellValidated(C1)
    OnRowValidating(R1)
    OnRowValidated(R1)
    OnRowEnter(R2)
    OnCellEnter(C2)
             * 
             */
            //Setup the events for that the Projected and Actual Sales DataGridViews will share.
            //Events are assigned with regard to which event gets triggered first and so on..
            projectionsDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
            actualDataGridView.CellValidating += ValidateSalesDataGridViewCellContents;
        }

        #region APC DataGridView Events

        /// <summary>
        /// Event Used: RowsAdded
        /// Draws the row number in the row's cell header whenever a row is added.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void DisplayRowNumbers(object sender, DataGridViewRowsAddedEventArgs e)
        {
            var table = ((DataGridView)sender);
            table.Rows[e.RowIndex].HeaderCell.Value = (e.RowIndex + 1).ToString();
        }

        #endregion

        #region Sales DataGridView Events

        /// <summary>
        /// Event Used: CellValidating
        /// Validates the contents of a cell, before leaving it. If the contents
        /// are valid then the appropriate formatting is applied if needed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ValidateSalesDataGridViewCellContents(object sender, DataGridViewCellValidatingEventArgs e)
        {
            //Grab the DataGirdView that fired the event and make it into a local variable.
            var dataGridView = ((DataGridView)sender);
            //
            var textInfo = new CultureInfo("en-US", false).TextInfo;
            //Check for isNewRow if it is, return no need to check it for anything.
            if (dataGridView.Rows[e.RowIndex].IsNewRow)
            {
                return;
            }

            //Check to see if the current column is the ad item column.
            if (e.ColumnIndex == 0)
            {
                var adItemText = dataGridView.Rows[e.RowIndex].Cells[0].EditedFormattedValue.ToString();
                //If there is text after all the whitespace has been cleared, clear the error text property regardless of whether or not it is set.
                if (!string.IsNullOrEmpty(Regex.Replace(adItemText, @"\s+", "")))
                {
                    //Clear the error text since there is in fact an item entered.
                    dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "";
                    //Send the ad item text through the formatting engine and assign the new value to the cell.
                    dataGridView.Rows[e.RowIndex].Cells[0].Value = TextFormat.FormatAdItemText(adItemText);
                    //Force a refresh so the cell's text updates and displays for the user.
                    dataGridView.RefreshEdit();
                    return;
                }
                //If column one (1) is blank then cancel cell validating.
                if (e.ColumnIndex == 0 && Regex.Replace(adItemText, @"\s+", "") == "") dataGridView.Rows[e.RowIndex].Cells[0].ErrorText = "Ad Item needed"; return;
            }
            //Check to see if the cell is in the "Sold" column.
            if (e.ColumnIndex == 1)
            {
                //This Reg-ex pattern will match any number followed by the word bin(s), to allow specifying the number of bins of product were ordered.
                var inventoryStringCheck = new Regex(@"^[0-9]{1,2} \bbin(s){0,1}\b", RegexOptions.IgnoreCase);
                if (
                    inventoryStringCheck.IsMatch(
                        dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString()))
                {
                    //IF a match has been found, then make sure the word 'bin(s)' is capitalized to keep things looking pretty.
                    var input = textInfo.ToTitleCase(dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString());
                    dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = input;
                    dataGridView.RefreshEdit();
                    return;
                }
            }
            //If the column is the "Sale Price" column try to parse the contents to a Double and apply number formatting to the contents.
            //Check for the cost column to see if there are any strings formatted like such:
            var regExpression = new Regex(@"^\d+( *)?/( *)?\${0,1}?\d+(\.\d+)?", RegexOptions.IgnoreCase); // [0-9]/($)?[0-9]
            //IF the current cell is in the sale price column, check for the string format above, else move to the default method.
            if ((e.ColumnIndex == 2) && regExpression.IsMatch(dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString()))
            {
                //Grab the input and split it at the forward slash (/) for formatting.
                var input = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString();
                input = input.Replace(" ", "");
                //Remove any dollar signs as these cause errors.
                input = input.Replace("$", "");
                var stringArray = input.Split('/');
                //Format the last number as Currency, and round it up if necessary.
                dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value =
                    $@"{stringArray[0]}/{Math.Round(decimal.Parse(stringArray[1]), 2):C}";
                //Always refresh edit so the new value shows up to the user.
                dataGridView.RefreshEdit();
                return; //And return, there is no need to go further.
            }
            //If the column is any other then check to see if the entered value can be parsed to a double (is a number), if not then throw an error to the user.
            double parsedUserInput;
            if (
                !double.TryParse(
                    dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString(),
                    out parsedUserInput))
            {
                MessageBox.Show(@"Non numeric characters in column " + (e.ColumnIndex + 1) + @" are not allowed.", @"Invalid Characters Detected");
                e.Cancel = true;
                dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = "";
                dataGridView.RefreshEdit();
                return;
            }
            //IF the index is greater then two (2), then that means we are not in a column that requires special formatting out side of currency.
            if (e.ColumnIndex <= 2) return;
            //IF not, then apply currency formatting to the cell.
            var value = double.Parse(dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].EditedFormattedValue.ToString(), NumberStyles.Currency);
            //If all goes well, format the string in question by adding commas and decimal points if applicable.
            dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Math.Round(value, 2).ToString("N", new CultureInfo("en-US"));
            //Always refresh edit so the new value shows up to the user.
            dataGridView.RefreshEdit();
        }

        #endregion

        #region Comments TextBox Events
        /// <summary>
        /// Event Used: KeyUp
        /// Calculates and displays the remaining number of characters left available for the user to enter,
        /// and changes the color of the label displaying the character count to red when 20% or less characters remain.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DisplayRemainingCommentCharacterCount(object sender, EventArgs e)
        {
            //If the amount of characters left is less then 20% (Or more 80% or more characters have been used) then color the label red, otherwise color it its default color.
            commentsGroupBox.ForeColor = (double)commentsTextBox.TextLength / commentsTextBox.MaxLength < .8 ? default(Color) : Color.DarkRed;
            commentsGroupBox.Text = @"Comments (Characters Remaining: " + (commentsTextBox.MaxLength - commentsTextBox.TextLength) + @")";
        }
        #endregion

        #region MonthCalendar Events
        /// <summary>
        /// Updates the week ending masked text box with the selected date
        /// using the format (MM/DD/YYYY).
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UpdateWeekEndingMaskedTextBox(object sender, DateRangeEventArgs e)
        {
            var selectedDate = weekEndingMonthCalendar.SelectionStart;
            if (!selectedDate.ToString("D").StartsWith("Saturday"))
            {
                weekEndingMaskedTextBox.ForeColor = Color.Maroon;
                weekEndingMaskedTextBoxInstructionLabel.Text = @"... or manually enter it here: *";
                errorLabel.Text = @"The date you selected does not appear to be a week ending date.";
            }
            else
            {
                weekEndingMaskedTextBox.ForeColor = Color.Black;
                weekEndingMaskedTextBoxInstructionLabel.Text = @"... or manually enter it here:";
                errorLabel.Text = "";
            }
            weekEndingMaskedTextBox.Text = selectedDate.ToString("MM-dd-yyyy");
        }

        #endregion

        #region Data Grid View Construction Functions



        #endregion

    }
}
