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

namespace ImageBlockz.Core
{
    /// <summary>
    /// Provides a control that can be used to enter decadic or integer values to the application.
    /// </summary>
    public partial class DigitBox : UserControl
    {
        private int min = -32768;
        private int max = 32767;
        private ValueType type = ValueType.Int;
        private float decValue = 0;
        private bool isOK = true;

        /// <summary>
        /// Definition of delegate for event handling.
        /// </summary>
        /// <param name="sender">Object, which call this event.</param>
        /// <param name="e">Event data.</param>
        public delegate void ValueChangedHandler(object sender, EventArgs e);
        private event ValueChangedHandler valueChanged;

        /// <summary>
        /// Implements enumerator for types of values.
        /// </summary>
        public enum ValueType
        {
            Int = 0, Dec = 1
        }

        /// <summary>
        /// Constructor of DigitBox class.
        /// </summary>
        public DigitBox()
        {
            InitializeComponent();

            myDigitBox.Text = decValue.ToString();            
        }

        /// <summary>
        /// Method for adding and removing handler.
        /// </summary>
        public event ValueChangedHandler ValueChangedEvent
        {
            add
            {
                valueChanged += value;
            }
            remove
            {
                valueChanged -= value;
            }
        }

        /// <summary>
        /// Gets or sets minimal valid value.
        /// </summary>
        public int Min
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets maximal valid value.
        /// </summary>
        public int Max
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets <see cref="ValueType"> type </see> .
        /// </summary>
        public ValueType Type
        {
            get;
            set;    
        }

        /// <summary>
        /// Gets or sets <see cref="float"> value </see>.
        /// </summary>
        public float Value
        {
            get
            {
                return decValue;
            }
            set
            {
                if (value - Math.Truncate(value) != 0 && type == ValueType.Int)
                {
                    isOK = false;
                    return;
                }

                Validate(value);

                decValue = value;

                myDigitBox.Text = value.ToString();
            }
        }

        /// <summary>
        /// This method provides information if is value in DigitBox valid.
        /// </summary>
        /// <returns></returns>
        public bool IsOK()
        {
            return isOK;
        }
        
        /// <summary>
        /// Set DigitBox to <see cref="ValueType">type</see> and minimal and maximal value.
        /// </summary>
        /// <param name="type">Type of value.</param>
        /// <param name="min">Minimal valid value in DigitBox.</param>
        /// <param name="max">Maximal valid value in DigitBox.</param>
        public void SetDigitBox(ValueType type, int min, int max)
        {
            this.type = type;
            this.min = min;
            this.max = max;
        }

        /// <summary>
        /// Set DigitBox to <see cref="ValueType">type</see>.
        /// </summary>
        /// <param name="type">Type of value.</param>
        public void SetDigitBox(ValueType type)
        {
            this.type = type;
        }

        /// <summary>
        /// Set DigitBox to <see cref="ValueType">type</see>, minimal and maximal value and default value.
        /// </summary>
        /// <param name="type">Type of value.</param>
        /// <param name="min">Minimal valid value in DigitBox.</param>
        /// <param name="max">Maximal valid value in DigitBox.</param>
        /// <param name="defaultValue">Default Value of DigitBox.</param>
        public void SetDigitBox(ValueType type, int min, int max, float defaultValue)
        {
            this.type = type;
            this.min = min;
            this.max = max;
            this.decValue = defaultValue;
        }

        private void OnDialogOK()
        {
            string text =  myDigitBox.Text;

            int intValue = 0;
            decValue = 0;

            if (type == ValueType.Int)
            { 
                isOK = Int32.TryParse(text, out intValue);
                decValue = intValue;
            }
            else if (type == ValueType.Dec)
            {
                isOK = float.TryParse(text, out decValue);
            }
            else
            {
                myDigitBox.Enabled = false;
                myDigitBox.Text = "Wrong Type (Error In Code).";
            }

            Validate(decValue);
        }

        private void myDigitBox_TextChanged(object sender, EventArgs e)
        {
            if (valueChanged != null)
            {
                valueChanged(this, e);
            }

            OnDialogOK();

            Validate(decValue); 

        }

        /// <summary>
        /// Validates Value in DigitBox along with set type, minimum and maximum.
        /// </summary>
        /// <param name="value">Value in DigitBox.</param>
        public void Validate(float value)
        {
            if (value < min || value > max)
            {
                isOK = false;
            }
 
            if (isOK == false)
            {
                myDigitBox.BackColor = Color.Salmon;
            }
            else
            {
                myDigitBox.BackColor = SystemColors.Window;
            }
        }

        /// <summary>
        /// Get Value from DigitBox.
        /// </summary>
        /// <returns>Value in DigitBox.</returns>
        public float GetValue()
        {
            OnDialogOK();

            return decValue;
        }
    }
}
