using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using C1.Win.C1Input;
using C1.Util.Localization;

namespace C1.Win.Chart.AxisScrollbar
{
    /// <summary>
    /// Represents a FlexChart range slider control supporting additional visual styles.
    /// </summary>
    [C1Description("RangeSelector", "A FlexChart range slider control supporting additional visual styles.")]
    [DefaultEvent("ValueChanged")]
    public partial class AxisScrollbar : UserControl
    {

        #region ** private variables

        private Axis _parentAxis;
        private FlexChart _parentChart;

        private bool _scrollButtonsVisible = true;
        private Orientation _orientation = Orientation.Horizontal;

        #endregion

        #region ** public properties
        /// <summary>
        /// Gets or sets the current lower magnitude of the range control.
        /// </summary>
        [C1Category("Data")]
        [C1Description("C1RangeSlider.LowerValue", "Gets or sets the current lower magnitude of the range control.")]
        [RefreshProperties(RefreshProperties.Repaint)]
        [MergableProperty(true)]
        [DefaultValue(0)]
        public double LowerValue
        {
            get { return rangeSlider.LowerValue; }
            set {rangeSlider.LowerValue = value;}
        }

        /// <summary>
        /// Gets or sets the current upper magnitude of the range control.
        /// </summary>
        [C1Category("Data")]
        [C1Description("C1RangeSlider.UpperValue", "Gets or sets the current upper magnitude of the range control.")]
        [RefreshProperties(RefreshProperties.Repaint)]
        [MergableProperty(true)]
        [DefaultValue(100)]
        public double UpperValue
        {
            get { return rangeSlider.UpperValue; }
            set { rangeSlider.UpperValue = value; }
        }

        /// <summary>
        /// Gets or sets the minimum possible value of the range element.
        /// </summary>
        [C1Category("Data")]
        [C1Description("C1RangeSlider.Minimum", "Gets or sets the minimum possible value of the range element.")]
        [RefreshProperties(RefreshProperties.Repaint)]
        [MergableProperty(true)]
        [DefaultValue(0)]
        public double Minimum
        {
            get { return rangeSlider.Minimum; }
            set { rangeSlider.Minimum = value; }
        }

        /// <summary>
        /// Gets or sets the maximum possible value of the range element.
        /// </summary>
        [C1Category("Data")]
        [C1Description("C1RangeSlider.Maximum", "Gets or sets the maximum possible value of the range element.")]
        [RefreshProperties(RefreshProperties.Repaint)]
        [MergableProperty(true)]
        [DefaultValue(100)]
        public double Maximum
        {
            get { return rangeSlider.Maximum; }
            set { rangeSlider.Maximum = value; }
        }

        [C1Category("Appearance")]
        [C1Description("C1RangeSlider.ScrollButtonsVisible", "Gets or sets a value that indicates whether scroll buttons should be displayed.")]
        [DefaultValue(true)]
        public bool ScrollButtonsVisible
        {
            get { return _scrollButtonsVisible; }
            set { 
                if (_scrollButtonsVisible == value) return;
                this.btnScrollLeft.Visible = value;
                this.btnScrollRight.Visible = value;
                _scrollButtonsVisible = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating the horizontal or vertical orientation of the C1RangeSlider.
        /// </summary>
        [C1Category("Appearance")]
        [C1Description("C1RangeSlider.Orientation", "Gets or sets a value indicating the horizontal or vertical orientation of the C1RangeSlider.")]
        [DefaultValue(Orientation.Horizontal)]
        public Orientation Orientation
        {
            get { return _orientation; }
            set {
                if (_orientation == value) return;
                if (value == System.Windows.Forms.Orientation.Horizontal)
                {
                    btnScrollLeft.Dock = DockStyle.Left;
                    btnScrollRight.Dock = DockStyle.Right;
                }
                else
                {
                    btnScrollLeft.Dock = DockStyle.Top;
                    btnScrollRight.Dock = DockStyle.Bottom;
                }
                rangeSlider.Orientation = value;
                _orientation = value;
                OnOrientationChanged(EventArgs.Empty);
            }
        }
        #endregion

        #region ** events
        /// <summary>
        /// Fires when any of the properties: LowerValue or UpperValue changes.
        /// </summary>
        [C1Category("Property Changed")]
        [C1Description("C1RangeSlider.ValueChanged", "Fires when any of the properties: LowerValue or UpperValue changes.")]
        public event EventHandler ValueChanged;

        /// <summary>
        /// This method is for internal use only.
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnValueChanged(EventArgs e)
        {
            if (ValueChanged != null)
            {
                ValueChanged(this, e);
            }
        }

        /// <summary>
        /// Fires when the <see cref="Orientation"/> property changes.
        /// </summary>
        [C1Category("Property Changed")]
        [C1Description("C1RangeSlider.OrientationChanged", "Fires when the Orientation property changes.")]
        public event EventHandler OrientationChanged;

        /// <summary>
        /// This method is for internal use only.
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnOrientationChanged(EventArgs e)
        {
            if (OrientationChanged != null)
            {
                OrientationChanged(this, e);
            }
        }
        #endregion

        #region ** constructor
        public AxisScrollbar(Axis axis):base()
        {
            if (axis == null) throw new ArgumentNullException();
            if ((axis.Chart as FlexChart) == null) throw new ArgumentNullException();

            InitializeComponent();

            //Set range selector styles
            SetRangeSliderDefaultStyles();

            //Geting chart paremeters
            _parentAxis = axis;
            _parentChart = (FlexChart)axis.Chart;
            UpperValue = Maximum = axis.ActualMax;
            LowerValue = Minimum = axis.ActualMin;
            _parentChart.Paint += ParentChart_Paint;

            rangeSlider.ValueChanged += rangeSlider_ValueChanged;

            if (axis.AxisType == C1.Chart.AxisType.X)
                Orientation = System.Windows.Forms.Orientation.Horizontal;
            else if (axis.AxisType == C1.Chart.AxisType.Y)
                Orientation = System.Windows.Forms.Orientation.Vertical;

            SetRangeSelectorSize();

            //Add RangeSelector to the chart
            _parentChart.Controls.Add(this);
        }
        #endregion

        #region ** implementation

        private void SetRangeSliderDefaultStyles()
        {
            rangeSlider.IsRangeBarVisible = false;
            rangeSlider.Padding = new Padding(0);
            rangeSlider.ScrollBehavior = RangeSliderScrollBehavior.Range;
            rangeSlider.LargeChange = UpperValue - LowerValue;
            rangeSlider.IsDirectionReversed = false;
        }

        void rangeSlider_ValueChanged(object sender, EventArgs e)
        {
            OnValueChanged(e);
            rangeSlider.LargeChange = UpperValue - LowerValue;
        }
        void ParentChart_Paint(object sender, EventArgs e)
        {
            if (Orientation == System.Windows.Forms.Orientation.Horizontal && this.Width == (int)_parentChart.PlotRect.Width) return;
            if (Orientation == System.Windows.Forms.Orientation.Vertical && this.Height == (int)_parentChart.PlotRect.Height) return;
            SetRangeSelectorSize();
        }

        private void SetRangeSelectorSize()
        {
            if (Orientation == System.Windows.Forms.Orientation.Horizontal)
            {
                if (Width == _parentChart.PlotRect.Width) return;
                _parentChart.PlotMargin = new Padding(70, 0, 0, 60);
                this.Left = (int)_parentChart.PlotRect.Left;
                this.Top = _parentChart.Height - 30;
                this.Width = (int)_parentChart.PlotRect.Width;
                this.Height = 30;
            }
            else
            {
                if (Height == _parentChart.PlotRect.Height) return;
                this.Left = 0;
                this.Top = (int)_parentChart.PlotRect.Top;
                this.Width = 30;
                this.Height = (int)_parentChart.PlotRect.Height;
            }
        }

        /// <summary>
        /// Removes itself from parent control
        /// </summary>
        public virtual void Remove()
        {
            _parentChart.AxisX.Min = _parentChart.AxisX.Max = Double.NaN;
            _parentChart.Paint -= ParentChart_Paint;
            if (this.Parent != null)
                this.Parent.Controls.Remove(this);
        }

        private void btnScrollLeft_Click(object sender, EventArgs e)
        {
            rangeSlider.LowerValue--;
        }

        private void btnScrollRight_Click(object sender, EventArgs e)
        {
            rangeSlider.UpperValue++;
        }
        #endregion

    }
}
