using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

namespace Betfair.Gamex.API.UberClient.Controls
{
    /// <summary>
    /// This is a custom control which allows only numerical data input. 
    /// </summary>
    public class NumericEdit : TextBox
    {
        private NumEditType m_inpType;
        private float m_max;

        /// <summary>
        /// Enumeration of data types which control accepts.
        /// </summary>
        public enum NumEditType
        {
            /// <summary>
            /// Currency data
            /// </summary>
            Currency,
        }

        /// <summary>
        /// Ctor for Numeric Edit Control
        /// </summary>
        public NumericEdit()
        {
            this.InputType = NumEditType.Currency;
            this.ContextMenu = new ContextMenu();
        }

        /// <summary>
        /// Gets/Sets the InputType
        /// </summary>
        [Description("Sets the numeric type allowed"), Category("Behavior")]
        public NumEditType InputType
        {
            get
            {
                return m_inpType; 
            }
            set
            {
                m_inpType = value;
            }
        }

        /// <summary>
        /// Gets/Sets the Maximum allowed value.
        /// </summary>
        [Description("Sets the Maximum allowed value"), Category("Behavior")]
        public float Max
        {
            get { return m_max; }
            set { m_max = value; }
        }

        /// <summary>
        /// Gets/Sets the text to be displayed.
        /// </summary>
        public override string Text
        {
            get 
            { 
                return base.Text;
            }
            set
            {
                if (IsValid(value, true))
                    base.Text = value;
            }
        }

        private bool IsValid(string val, bool user)
        {
            bool ret = true;

            if (string.IsNullOrEmpty(val) || val.Equals("+"))
                return ret;

            if (user)
            {
                if (val.Equals("-") || val.Equals(","))
                    return ret;
            }

            try
            {
                switch (m_inpType)
                {
                    case NumEditType.Currency:
                        decimal dec = decimal.Parse(val);
                        if (dec == 0) // CG 12/5/06 don't allow user to enter multiple leading zeros
                        {
                            if ((val.Length == 2) && (val[1] != '.')) // only allow '.' when on their second character if dev = 0
                                return false;
                            if (val.Length > 2) //not allowed to enter another 0
                                return false;
                        }
                        if (CheckMax(double.Parse(dec.ToString())))
                        {
                            return false;
                        }
                        int pos = val.IndexOf(".");
                        if (pos != -1)
                        {
                            if (val.Substring(pos).Length <= 3)
                            {
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }
                        break;
                    default:
                        throw new ApplicationException();
                }
            }
            catch
            {
                ret = false;
            }
            return ret;
        }

        /// <summary>
        /// This method is called during message preprocessing to handle command keys
        /// In addition to the key the user pressed, the key data also indicates which, 
        /// if any, modifier keys were pressed at the same time as the key. 
        /// Modifier keys include the SHIFT, CTRL, and ALT keys
        /// </summary>
        /// <param name="msg">A Message, passed by reference, that represents the window message to process.</param>
        /// <param name="keyData">One of the Keys values that represents the key to process.</param>
        /// <returns>true if the character was processed by the control; otherwise, false.</returns>
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == (Keys)Shortcut.CtrlV || keyData == (Keys)Shortcut.ShiftIns)
            {
                IDataObject iData = Clipboard.GetDataObject();
                string newText;
                newText = base.Text.Substring(0, base.SelectionStart) + (string)iData.GetData(DataFormats.Text) + base.Text.Substring(base.SelectionStart + base.SelectionLength);

                if (newText.Length > 1)
                {
                    return true;
                }

                if (!IsValid(newText, true))
                    return true;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        /// <summary>
        /// This event is raised when the user leaves the control.
        /// </summary>
        /// <param name="e">An EventArgs that contains the event data. </param>
        protected override void OnLeave(EventArgs e)
        {
            // handle - and leading zeros input since KeyPress handler must allow this
            if (base.Text != string.Empty)
            {
                if (!IsValid(base.Text, false))
                    base.Text = string.Empty;
                else if (Double.Parse(base.Text) == 0)	// this used for -0, 000 and other strings
                    base.Text = "0";
            }
            base.OnLeave(e);
        }

        /// <summary>
        /// Event occurs after the KeyDown event and is used to prevent characters from entering the control.
        /// </summary>
        /// <param name="e">A KeyPressEventArgs that contains the event data. </param>
        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            char c = e.KeyChar;
            if (!Char.IsControl(c))
            {
                if (c.ToString() == " " || c.ToString() == "-" || c.ToString() == "+" || c.ToString() == ",")
                {
                    e.Handled = true;
                    return;
                }

                string newText = base.Text.Substring(0, base.SelectionStart) + c.ToString() + base.Text.Substring(base.SelectionStart + base.SelectionLength);
                if (!IsValid(newText, true))
                    e.Handled = true;
            }

            if (!(e.KeyChar == 31 || e.KeyChar == 30 || e.KeyChar == 28))
            {
                base.OnKeyPress(e);
            }
            else
            {
                e.Handled = true;
                base.OnKeyPress(e);
            }
        }

        private bool CheckMax(double Max)
        {
            bool ret;
            switch (m_inpType)
            {
                case NumEditType.Currency:
                    ret = Max > this.Max;
                    //if value if greate than max value returns true
                    break;
                default:
                    throw new ApplicationException();
            }
            return ret;
        }
    }
}
