using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using DevComponents.DotNetBar.Events;
namespace DevComponents.DotNetBar.Controls
{
    [ToolboxBitmap(typeof(SwitchButton), "Controls.SwitchButton.ico"), ToolboxItem(true), System.Runtime.InteropServices.ComVisible(false), Designer("DevComponents.DotNetBar.Design.SwitchButtonDesigner, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral,  PublicKeyToken=90f470f34c89ccaf")]
    [DefaultEvent("ValueChanged"), DefaultBindingProperty("Value"), DefaultProperty("Value")]
    public class SwitchButton : BaseItemControl, ICommandSource
    {
        #region Events
        /// 
        /// Occurs before Value property has changed and it allows you to cancel the change.
        /// 
        public event EventHandler ValueChanging;
        /// 
        /// Raises ValueChanging event.
        /// 
        /// Provides event arguments.
        protected virtual void OnValueChanging(EventArgs e)
        {
            EventHandler handler = ValueChanging;
            if (handler != null)
                handler(this, e);
        }
        /// 
        /// Occurs after Value property has changed.
        /// 
        public event EventHandler ValueChanged;
        /// 
        /// Raises ValueChanged event.
        /// 
        /// Provides event arguments.
        protected virtual void OnValueChanged(EventArgs e)
        {
            EventHandler handler = ValueChanged;
            if (handler != null)
                handler(this, e);
        }
        #endregion
        #region Constructor, Dispose
        private SwitchButtonItem _SwitchButton = null;
        public SwitchButton()
        {
            this.SetStyle(ControlStyles.Selectable, true);
            _SwitchButton = new SwitchButtonItem();
            _SwitchButton.TextVisible = false;
            _SwitchButton.ValueChanging += new EventHandler(SwitchButtonItemValueChanging);
            _SwitchButton.ValueChanged += new EventHandler(SwitchButtonItemValueChanged);
            this.HostItem = _SwitchButton;
        }
        #endregion
        #region Internal Implementation
        protected override void OnHandleCreated(EventArgs e)
        {
            this.RecalcLayout();
            base.OnHandleCreated(e);
        }
        /// 
        /// Forces the button to perform internal layout.
        /// 
        public override void RecalcLayout()
        {
            if (_SwitchButton == null) return;
            _SwitchButton.ButtonWidth = Math.Max(4, Dpi.DescaleWidth(this.Width - this.Padding.Horizontal));
            _SwitchButton.ButtonHeight = Math.Max(4, Dpi.DescaleHeight(this.Height - this.Padding.Vertical));
            base.RecalcLayout();
        }
        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Space && this.Enabled && !IsReadOnly)
            {
                _SwitchButton.SetValueAndAnimate(!_SwitchButton.Value, eEventSource.Keyboard);
            }
            base.OnKeyDown(e);
        }
        /// 
        /// Gets or sets the switch value.
        /// 
        [DefaultValue(false), Category("Appearance"), Description("Indicates switch value."), Bindable(true)]
        public bool Value
        {
            get { return _SwitchButton.Value; }
            set
            {
                _SwitchButton.Value = value;
            }
        }
        /// 
        /// Gets or sets the item border color.
        /// 
        [Category("Appearance"), Description("Indicates item border color.")]
        public Color BorderColor
        {
            get { return _SwitchButton.BorderColor; }
            set { _SwitchButton.BorderColor = value; }
        }
        /// 
        /// Gets whether property should be serialized.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeBorderColor()
        {
            return _SwitchButton.ShouldSerializeBorderColor();
        }
        /// 
        /// Resets property to its default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetBorderColor()
        {
            this.BorderColor = Color.Empty;
        }
        /// 
        /// Cancels animation if in progress.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void CancelAnimation()
        {
            _SwitchButton.CancelAnimation();
        }
        /// 
        /// Gets or sets whether state transition animation is enabled.
        /// 
        [DefaultValue(true), Category("Appearance"), Description("Indicates whether state transition animation is enabled.")]
        public bool AnimationEnabled
        {
            get { return _SwitchButton.AnimationEnabled; }
            set
            {
                _SwitchButton.AnimationEnabled = value;
            }
        }
        void SwitchButtonItemValueChanged(object sender, EventArgs e)
        {
            _ValueObject = GetValueObject(this.Value);
            ExecuteCommand();
            OnValueChanged(e);
            OnValueObjectChanged(e);
        }
        void SwitchButtonItemValueChanging(object sender, EventArgs e)
        {
            OnValueChanging(e);
        }
        protected override System.Drawing.Size DefaultSize
        {
            get
            {
                return new System.Drawing.Size(66, 22);
            }
        }
        protected override void OnPaddingChanged(EventArgs e)
        {
            _SwitchButton.Margin.Bottom = this.Padding.Bottom;
            _SwitchButton.Margin.Top = this.Padding.Top;
            _SwitchButton.Margin.Left = this.Padding.Left;
            _SwitchButton.Margin.Right = this.Padding.Right;
            base.OnPaddingChanged(e);
        }
        /// 
        /// Gets or sets the color of the OFF state background.
        /// 
        [Category("Appearance"), Description("Indicates color of OFF state background.")]
        public Color OffBackColor
        {
            get { return _SwitchButton.OffBackColor; }
            set { _SwitchButton.OffBackColor = value; }
        }
        /// 
        /// Gets whether property should be serialized.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeOffBackColor()
        {
            return _SwitchButton.ShouldSerializeOffBackColor();
        }
        /// 
        /// Resets property to its default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetOffBackColor()
        {
            this.OffBackColor = Color.Empty;
        }
        /// 
        /// Gets or sets the color of the ON state background.
        /// 
        [Category("Appearance"), Description("Indicates color of ON state background.")]
        public Color OnBackColor
        {
            get { return _SwitchButton.OnBackColor; }
            set { _SwitchButton.OnBackColor = value; }
        }
        /// 
        /// Gets whether property should be serialized.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeOnBackColor()
        {
            return _SwitchButton.ShouldSerializeOnBackColor();
        }
        /// 
        /// Resets property to its default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetOnBackColor()
        {
            this.OnBackColor = Color.Empty;
        }
        /// 
        /// Gets or sets the color of the ON state text.
        /// 
        [Category("Appearance"), Description("Indicates color of ON state text.")]
        public Color OnTextColor
        {
            get { return _SwitchButton.OnTextColor; }
            set { _SwitchButton.OnTextColor = value; }
        }
        /// 
        /// Gets whether property should be serialized.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeOnTextColor()
        {
            return _SwitchButton.ShouldSerializeOnTextColor();
        }
        /// 
        /// Resets property to its default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetOnTextColor()
        {
            this.OnTextColor = Color.Empty;
        }
        /// 
        /// Gets or sets the color of the OFF state text.
        /// 
        [Category("Appearance"), Description("Indicates color of OFF state text.")]
        public Color OffTextColor
        {
            get { return _SwitchButton.OffTextColor; }
            set { _SwitchButton.OffTextColor = value; }
        }
        /// 
        /// Gets whether property should be serialized.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeOffTextColor()
        {
            return _SwitchButton.ShouldSerializeOffTextColor();
        }
        /// 
        /// Resets property to its default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetOffTextColor()
        {
            this.OffTextColor = Color.Empty;
        }
        /// 
        /// Gets or sets the border color of the button switch.
        /// 
        [Category("Appearance"), Description("Indicates border color of the button switch.")]
        public Color SwitchBorderColor
        {
            get { return _SwitchButton.SwitchBorderColor; }
            set { _SwitchButton.SwitchBorderColor = value; }
        }
        /// 
        /// Gets whether property should be serialized.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeSwitchBorderColor()
        {
            return _SwitchButton.ShouldSerializeSwitchBorderColor();
        }
        /// 
        /// Resets property to its default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetSwitchBorderColor()
        {
            this.SwitchBorderColor = Color.Empty;
        }
        /// 
        /// Gets or sets the background color of the switch button.
        /// 
        [Category("Appearance"), Description("Indicates background color of the switch button.")]
        public Color SwitchBackColor
        {
            get { return _SwitchButton.SwitchBackColor; }
            set { _SwitchButton.SwitchBackColor = value; }
        }
        /// 
        /// Gets whether property should be serialized.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeSwitchBackColor()
        {
            return _SwitchButton.ShouldSerializeSwitchBackColor();
        }
        /// 
        /// Resets property to its default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetSwitchBackColor()
        {
            this.SwitchBackColor = Color.Empty;
        }
        /// 
        /// Gets or sets the text color.
        /// 
        [Category("Appearance"), Description("Indicates text color."), Browsable(false)]
        public Color TextColor
        {
            get { return _SwitchButton.TextColor; }
            set { _SwitchButton.TextColor = value; }
        }
        /// 
        /// Gets whether property should be serialized.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeTextColor()
        {
            return _SwitchButton.ShouldSerializeTextColor();
        }
        /// 
        /// Resets property to its default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetTextColor()
        {
            this.TextColor = Color.Empty;
        }
        /// 
        /// Gets or sets the font that is used to draw ON/OFF text on the switch button.
        /// 
        [DefaultValue(null), Category("Appearance"), Description("Indicates font that is used to draw ON/OFF text on the switch button.")]
        public Font SwitchFont
        {
            get { return _SwitchButton.SwitchFont; }
            set { _SwitchButton.SwitchFont = value; }
        }
        /// 
        /// Gets or sets the text that is displayed on switch when Value property is set to true.
        /// 
        [DefaultValue("ON"), Localizable(true), Category("Appearance"), Description("Indicates text that is displayed on switch when Value property is set to true.")]
        public string OnText
        {
            get { return _SwitchButton.OnText; }
            set
            {
                _SwitchButton.OnText = value;
            }
        }
        /// 
        /// Gets or sets the text that is displayed on switch when Value property is set to false.
        /// 
        [DefaultValue("OFF"), Localizable(true), Category("Appearance"), Description("Indicates text that is displayed on switch when Value property is set to true.")]
        public string OffText
        {
            get { return _SwitchButton.OffText; }
            set
            {
                _SwitchButton.OffText = value;
            }
        }
        [Browsable(false)]
        public override eDotNetBarStyle Style
        {
            get
            {
                return base.Style;
            }
            set
            {
                base.Style = value;
            }
        }
        [Browsable(false)]
        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {
                base.Text = value;
            }
        }
        [Browsable(false)]
        public override Color ForeColor
        {
            get
            {
                return base.ForeColor;
            }
            set
            {
                base.ForeColor = value;
            }
        }
        /// 
        /// Gets or sets the width in pixels of the switch part of the button. Minimum value is 6.
        /// 
        [DefaultValue(28), Category("Appearance"), Description("Indicates width in pixels of the switch part of the button.")]
        public int SwitchWidth
        {
            get { return _SwitchButton.SwitchWidth; }
            set
            {
                _SwitchButton.SwitchWidth = value;
            }
        }
        /// 
        /// Gets the switch bounds.
        /// 
        [Browsable(false)]
        public Rectangle SwitchBounds
        {
            get { return _SwitchButton.SwitchBounds; }
        }
        /// 
        /// Gets the On part of the switch button bounds excluding the SwitchBounds.
        /// 
        [Browsable(false)]
        public Rectangle OnPartBounds
        {
            get { return _SwitchButton.OnPartBounds; }
        }
        /// 
        /// Gets the Off part of the switch button bounds excluding the SwitchBounds.
        /// 
        [Browsable(false)]
        public Rectangle OffPartBounds
        {
            get { return _SwitchButton.OffPartBounds; }
        }
        /// 
        /// Sets the value of the control with state transition animation (if enabled) and specifies the source of the action.
        /// 
        /// New value for Value property.
        /// Source of the action.
        public void SetValueAndAnimate(bool value, eEventSource source)
        {
            _SwitchButton.SetValueAndAnimate(value, source);
        }
        /// 
        /// Sets the value of the control and specifies the source of the action.
        /// 
        /// New value for Value property.
        /// Source of the action.
        public void SetValue(bool newValue, eEventSource source)
        {
            _SwitchButton.SetValue(newValue, source);
        }
        /// 
        /// Gets or sets whether button is in read-only state meaning that it appears as enabled but user cannot change its state.
        /// 
        [DefaultValue(false), Category("Behavior"), Description("Indicates whether button is in read-only state meaning that it appears as enabled but user cannot change its state.")]
        public bool IsReadOnly
        {
            get { return _SwitchButton.IsReadOnly; }
            set { _SwitchButton.IsReadOnly = value; }
        }
        /// 
        /// Gets or sets whether lock marker is visible on face of the control when IsReadOnly is set to true.
        /// Default value is true.
        /// 
        [DefaultValue(true), Category("Appearance"), Description("Indicates whether lock marker is visible on face of the control when IsReadOnly is set to true.")]
        public bool ShowReadOnlyMarker
        {
            get { return _SwitchButton.ShowReadOnlyMarker; }
            set { _SwitchButton.ShowReadOnlyMarker = value; }
        }
        /// 
        /// Gets or sets the color of the read-only marker.
        /// 
        [Category("Appearance"), Description("Indicates color of read-only marker.")]
        public Color ReadOnlyMarkerColor
        {
            get { return _SwitchButton.ReadOnlyMarkerColor; }
            set { _SwitchButton.ReadOnlyMarkerColor = value; }
        }
        /// 
        /// Gets whether property should be serialized.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public bool ShouldSerializeReadOnlyMarkerColor()
        {
            return _SwitchButton.ShouldSerializeReadOnlyMarkerColor();
        }
        /// 
        /// Resets property to its default value.
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public void ResetReadOnlyMarkerColor()
        {
            _SwitchButton.ResetReadOnlyMarkerColor();
        }
        public override Size GetPreferredSize(Size proposedSize)
        {
            if (_SwitchButton != null)
                return _SwitchButton.GetPreferredSize();
            return base.GetPreferredSize(proposedSize);
        }
        /// 
        /// Indicates whether clicking left mouse button on the switch part of the item will toggle the switch Value.
        /// 
        [DefaultValue(false), Category("Behavior"), Description("Indicates whether clicking left mouse button on the switch part of the item will toggle the switch Value.")]
        public bool SwitchClickTogglesValue
        {
            get { return _SwitchButton.SwitchClickTogglesValue; }
            set { _SwitchButton.SwitchClickTogglesValue = value; }
        }
        #endregion
        #region ValueObject implementation
        private const string DefaultValueFalse = "N";
        private const string DefaultValueTrue = "Y";
        private object _ValueObject = DefaultValueFalse;
        private object _ValueFalse= DefaultValueFalse;
        private object _ValueTrue= DefaultValueTrue;
        /// 
        /// Occurs after ValueObject property changes.
        /// 
        [Description("Occurs after ValueObject property changes.")]
        public event EventHandler ValueObjectChanged;
        /// 
        /// Raises ValueObjectChanged event.
        /// 
        /// Provides event arguments.
        protected virtual void OnValueObjectChanged(EventArgs e)
        {
            EventHandler handler = ValueObjectChanged;
            if (handler != null)
                handler(this, e);
        }
        /// 
        /// Gets or sets the object that represents the Value state of control.
        /// 
        [DefaultValue("N"), Bindable(true), RefreshProperties(RefreshProperties.All), TypeConverter(typeof(StringConverter)), Description("Indicates object that represents the Value state of control.")]
        public object ValueObject
        {
            get { return _ValueObject; }
            set
            {
                _ValueObject = value;
                OnValueObjectChanged();
            }
        }
        private void OnValueObjectChanged()
        {
            bool value = GetValue(_ValueObject);
            this.Value = value;
        }
        private bool IsNull(object value)
        {
            return value == null || value is string && (string)value == string.Empty ||
                value == DBNull.Value;
        }
        private object GetValueObject(bool value)
        {
            return value ? _ValueTrue : _ValueFalse;
        }
        private bool GetValue(object value)
        {
            if (_ValueTrue != null && _ValueTrue.Equals(value))
            {
                return true;
            }
            else if (_ValueFalse == null && IsNull(value) || _ValueFalse != null && _ValueFalse.Equals(value))
            {
                return false;
            }
            else
            {
                if (value is System.Data.SqlTypes.SqlBoolean)
                {
                    System.Data.SqlTypes.SqlBoolean sqlBool = (System.Data.SqlTypes.SqlBoolean)value;
                    return sqlBool.IsTrue;
                }
                else if (value is int?)
                {
                    if (value == null) return false;
                    if (((int?)value).Value == 0)
                        return false;
                    return true;
                }
                else if (value is int)
                {
                    return ((int)value) == 0 ? false : true;
                }
                else if (value is long)
                {
                    return ((long)value) == 0 ? false : true;
                }
                else if (value is short)
                {
                    return ((short)value) == 0 ? false : true;
                }
                else if (value is float)
                {
                    return ((float)value) == 0 ? false : true;
                }
                else if (value is double)
                {
                    return ((double)value) == 0 ? false : true;
                }
                else if (value is byte)
                {
                    return ((byte)value) == 0 ? false : true;
                }
                else if (value is uint)
                {
                    return ((uint)value) == 0 ? false: true;
                }
                else if (value is ulong)
                {
                    return ((ulong)value) == 0 ? false : true;
                }
                else if (value is bool)
                {
                    return ((bool)value);
                }
                return false;
            }
        }
        /// 
        /// Gets or sets the value that represents the True state of control when ValueObject property is set to that value.
        /// 
        [Browsable(true), DefaultValue("Y"), Category("Behavior"), TypeConverter(typeof(StringConverter)), Description("Represents the True state of Value when ValueObject property is set to that value.")]
        public object ValueTrue
        {
            get { return _ValueTrue; }
            set { _ValueTrue = value; OnValueObjectChanged(); }
        }
        /// 
        /// Gets or sets the value that represents the False state of control when ValueObject property is set to that value.
        /// 
        [Browsable(true), DefaultValue("N"), Category("Behavior"), TypeConverter(typeof(StringConverter)), Description("Represents the False state of control when ValueObject property is set to that value.")]
        public object ValueFalse
        {
            get { return _ValueFalse; }
            set { _ValueFalse = value; OnValueObjectChanged(); }
        }
        #endregion
        #region ICommandSource Members
        protected virtual void ExecuteCommand()
        {
            if (_Command == null) return;
            CommandManager.ExecuteCommand(this);
        }
        /// 
        /// Gets or sets the command assigned to the item. Default value is null.
        /// Note that if this property is set to null Enabled property will be set to false automatically to disable the item.
        /// 
        [DefaultValue(null), Category("Commands"), Description("Indicates the command assigned to the item.")]
        public Command Command
        {
            get { return (Command)((ICommandSource)this).Command; }
            set
            {
                ((ICommandSource)this).Command = value;
            }
        }
        private ICommand _Command = null;
        //[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        ICommand ICommandSource.Command
        {
            get
            {
                return _Command;
            }
            set
            {
                bool changed = false;
                if (_Command != value)
                    changed = true;
                if (_Command != null)
                    CommandManager.UnRegisterCommandSource(this, _Command);
                _Command = value;
                if (value != null)
                    CommandManager.RegisterCommand(this, value);
                if (changed)
                    OnCommandChanged();
            }
        }
        /// 
        /// Called when Command property value changes.
        /// 
        protected virtual void OnCommandChanged()
        {
        }
        private object _CommandParameter = null;
        /// 
        /// Gets or sets user defined data value that can be passed to the command when it is executed.
        /// 
        [Browsable(true), DefaultValue(null), Category("Commands"), Description("Indicates user defined data value that can be passed to the command when it is executed."), System.ComponentModel.TypeConverter(typeof(System.ComponentModel.StringConverter)), System.ComponentModel.Localizable(true)]
        public object CommandParameter
        {
            get
            {
                return _CommandParameter;
            }
            set
            {
                _CommandParameter = value;
            }
        }
        #endregion
    }
}