namespace PerpetuumSoft.Widgets
{
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Drawing.Design;

    [DefaultProperty("Value"), DefaultEvent("ValueChanged")]
    public abstract class LinearControlBase : ValuePresenter
    {
        private Color dangerColor = Color.Red;
        private int dangerValue = 80;
        private bool indicatorOnly = false;
        private string[] labels = new string[0];
        private int labelsCount = 5;
        private SliderElementsPosition labelsPosition = SliderElementsPosition.Both;
        private PerpetuumSoft.Widgets.Orientation orientation = PerpetuumSoft.Widgets.Orientation.Horizontal;
        private Color scaleColor = Color.Black;
        private PerpetuumSoft.Widgets.ScaleColorMode scaleColorMode = PerpetuumSoft.Widgets.ScaleColorMode.Sections;
        private int ticksCount = 10;
        private int ticksLenght = 8;
        private SliderElementsPosition ticksPosition = SliderElementsPosition.Both;
        private int ticksSubDivisionsCount = 5;
        private Color warningColor = Color.SaddleBrown;
        private int warningValue = 50;

        public LinearControlBase()
        {
            base.SetStyle(0x200, true);
        }

        protected override void Draw(Graphics g, Rectangle r)
        {
            base.Draw(g, r);
            this.DrawBar(g);
            this.DrawScale(g);
            this.DrawSlider(g);
        }

        protected virtual void DrawBar(Graphics g)
        {
        }

        protected virtual void DrawScale(Graphics g)
        {
            Rectangle indicatorRectangle = this.IndicatorRectangle;
            if (this.Orientation == PerpetuumSoft.Widgets.Orientation.Horizontal)
            {
                for (int i = 0; i <= this.ticksCount; i++)
                {
                    double num2 = this.Minimum + ((this.Maximum - this.Minimum) * (((double) i) / ((double) this.ticksCount)));
                    int num3 = indicatorRectangle.X + ((int) ((((double) i) / ((double) this.ticksCount)) * indicatorRectangle.Width));
                    Color valueColor = this.GetValueColor((int) num2);
                    if ((this.ticksPosition == SliderElementsPosition.TopLeft) || (this.ticksPosition == SliderElementsPosition.Both))
                    {
                        g.DrawLine(new Pen(valueColor), num3, indicatorRectangle.Y, num3, indicatorRectangle.Y - this.ticksLenght);
                    }
                    if ((this.ticksPosition == SliderElementsPosition.BottomRight) || (this.ticksPosition == SliderElementsPosition.Both))
                    {
                        g.DrawLine(new Pen(valueColor), num3, indicatorRectangle.Y + indicatorRectangle.Height, num3, (indicatorRectangle.Y + indicatorRectangle.Height) + this.ticksLenght);
                    }
                    if (this.ticksPosition == SliderElementsPosition.Internal)
                    {
                        g.DrawLine(new Pen(valueColor), num3, indicatorRectangle.Y + indicatorRectangle.Height, num3, indicatorRectangle.Y);
                    }
                    if (i != this.ticksCount)
                    {
                        for (int j = 1; j < this.ticksSubDivisionsCount; j++)
                        {
                            double num5 = num2 + ((this.Maximum - this.Minimum) * ((((double) j) / ((double) this.ticksCount)) / ((double) this.ticksSubDivisionsCount)));
                            int num6 = num3 + ((int) (((j * indicatorRectangle.Width) / ((double) this.ticksCount)) / ((double) this.ticksSubDivisionsCount)));
                            valueColor = this.GetValueColor((int) num5);
                            if ((this.ticksPosition == SliderElementsPosition.TopLeft) || (this.ticksPosition == SliderElementsPosition.Both))
                            {
                                g.DrawLine(new Pen(valueColor), num6, indicatorRectangle.Y, num6, indicatorRectangle.Y - (this.ticksLenght / 2));
                            }
                            if ((this.ticksPosition == SliderElementsPosition.BottomRight) || (this.ticksPosition == SliderElementsPosition.Both))
                            {
                                g.DrawLine(new Pen(valueColor), num6, indicatorRectangle.Y + indicatorRectangle.Height, num6, (indicatorRectangle.Y + indicatorRectangle.Height) + (this.ticksLenght / 2));
                            }
                            if (this.ticksPosition == SliderElementsPosition.Internal)
                            {
                                g.DrawLine(new Pen(valueColor), num6, indicatorRectangle.Y + (indicatorRectangle.Height / 4), num6, (indicatorRectangle.Y + indicatorRectangle.Height) - (indicatorRectangle.Height / 4));
                            }
                        }
                    }
                }
                if (this.labelsPosition != SliderElementsPosition.None)
                {
                    bool flag = (this.labels != null) && (this.labels.Length != 0);
                    int num7 = flag ? (this.labels.Length - 1) : this.labelsCount;
                    int num8 = indicatorRectangle.Y - (((this.ticksPosition == SliderElementsPosition.TopLeft) || (this.ticksPosition == SliderElementsPosition.Both)) ? this.ticksLenght : -2);
                    int num9 = (indicatorRectangle.Y + indicatorRectangle.Height) + (((this.ticksPosition == SliderElementsPosition.BottomRight) || (this.ticksPosition == SliderElementsPosition.Both)) ? this.ticksLenght : 2);
                    for (int k = 0; k <= num7; k++)
                    {
                        int v = this.Minimum + ((int) ((this.Maximum - this.Minimum) * (((double) k) / ((double) num7))));
                        int num12 = indicatorRectangle.X + ((int) ((((double) k) / ((double) num7)) * indicatorRectangle.Width));
                        Color color = this.GetValueColor(v);
                        string text = base.FormatValue(v);
                        if (flag)
                        {
                            text = this.labels[k];
                        }
                        Size size = g.MeasureString(text, this.Font).ToSize();
                        if ((this.labelsPosition == SliderElementsPosition.TopLeft) || (this.labelsPosition == SliderElementsPosition.Both))
                        {
                            g.DrawString(text, this.Font, new SolidBrush(color), (float) (num12 - (size.Width / 2)), (float) (num8 - size.Height));
                        }
                        if ((this.labelsPosition == SliderElementsPosition.BottomRight) || (this.labelsPosition == SliderElementsPosition.Both))
                        {
                            g.DrawString(text, this.Font, new SolidBrush(color), (float) (num12 - (size.Width / 2)), (float) num9);
                        }
                        if (this.labelsPosition == SliderElementsPosition.Internal)
                        {
                            g.DrawString(text, this.Font, new SolidBrush(color), (float) (num12 - (size.Width / 2)), (float) (this.CenterLine - (size.Height / 2)));
                        }
                    }
                }
            }
            else
            {
                for (int m = 0; m <= this.ticksCount; m++)
                {
                    double num14 = this.Minimum + ((this.Maximum - this.Minimum) * (((double) m) / ((double) this.ticksCount)));
                    int num15 = (indicatorRectangle.Height + indicatorRectangle.Y) - ((int) ((((double) m) / ((double) this.ticksCount)) * indicatorRectangle.Height));
                    Color color3 = this.GetValueColor((int) num14);
                    if ((this.ticksPosition == SliderElementsPosition.TopLeft) || (this.ticksPosition == SliderElementsPosition.Both))
                    {
                        g.DrawLine(new Pen(color3), indicatorRectangle.X, num15, indicatorRectangle.X - this.ticksLenght, num15);
                    }
                    if ((this.ticksPosition == SliderElementsPosition.BottomRight) || (this.ticksPosition == SliderElementsPosition.Both))
                    {
                        g.DrawLine(new Pen(color3), indicatorRectangle.X + indicatorRectangle.Width, num15, (indicatorRectangle.X + indicatorRectangle.Width) + this.ticksLenght, num15);
                    }
                    if (this.ticksPosition == SliderElementsPosition.Internal)
                    {
                        g.DrawLine(new Pen(color3), indicatorRectangle.X + indicatorRectangle.Width, num15, indicatorRectangle.X, num15);
                    }
                    if (m != this.ticksCount)
                    {
                        for (int n = 1; n < this.ticksSubDivisionsCount; n++)
                        {
                            double num17 = num14 + ((this.Maximum - this.Minimum) * ((((double) n) / ((double) this.ticksCount)) / ((double) this.ticksSubDivisionsCount)));
                            int num18 = num15 - ((int) (((n * indicatorRectangle.Height) / ((double) this.ticksCount)) / ((double) this.ticksSubDivisionsCount)));
                            color3 = this.GetValueColor((int) num17);
                            if ((this.ticksPosition == SliderElementsPosition.TopLeft) || (this.ticksPosition == SliderElementsPosition.Both))
                            {
                                g.DrawLine(new Pen(color3), indicatorRectangle.X, num18, indicatorRectangle.X - (this.ticksLenght / 2), num18);
                            }
                            if ((this.ticksPosition == SliderElementsPosition.BottomRight) || (this.ticksPosition == SliderElementsPosition.Both))
                            {
                                g.DrawLine(new Pen(color3), indicatorRectangle.X + indicatorRectangle.Width, num18, (indicatorRectangle.X + indicatorRectangle.Width) + (this.ticksLenght / 2), num18);
                            }
                            if (this.ticksPosition == SliderElementsPosition.Internal)
                            {
                                g.DrawLine(new Pen(color3), indicatorRectangle.X + (indicatorRectangle.Width / 4), num18, (indicatorRectangle.X + indicatorRectangle.Width) - (indicatorRectangle.Width / 4), num18);
                            }
                        }
                    }
                }
                if (this.labelsPosition != SliderElementsPosition.None)
                {
                    bool flag2 = (this.labels != null) && (this.labels.Length != 0);
                    int num19 = flag2 ? (this.labels.Length - 1) : this.labelsCount;
                    int num20 = indicatorRectangle.X - (((this.ticksPosition == SliderElementsPosition.TopLeft) || (this.ticksPosition == SliderElementsPosition.Both)) ? this.ticksLenght : -2);
                    int num21 = (indicatorRectangle.X + indicatorRectangle.Width) + (((this.ticksPosition == SliderElementsPosition.BottomRight) || (this.ticksPosition == SliderElementsPosition.Both)) ? this.ticksLenght : 2);
                    for (int num22 = 0; num22 <= num19; num22++)
                    {
                        int num23 = this.Minimum + ((int) ((this.Maximum - this.Minimum) * (((double) num22) / ((double) num19))));
                        int num24 = (indicatorRectangle.Y + indicatorRectangle.Height) - ((int) ((((double) num22) / ((double) num19)) * indicatorRectangle.Height));
                        Color color4 = this.GetValueColor(num23);
                        string str2 = base.FormatValue(num23);
                        if (flag2)
                        {
                            str2 = this.labels[num22];
                        }
                        Size size2 = g.MeasureString(str2, this.Font).ToSize();
                        if ((this.labelsPosition == SliderElementsPosition.TopLeft) || (this.labelsPosition == SliderElementsPosition.Both))
                        {
                            g.DrawString(str2, this.Font, new SolidBrush(color4), (float) (num20 - size2.Width), (float) (num24 - (size2.Height / 2)));
                        }
                        if ((this.labelsPosition == SliderElementsPosition.BottomRight) || (this.labelsPosition == SliderElementsPosition.Both))
                        {
                            g.DrawString(str2, this.Font, new SolidBrush(color4), (float) num21, (float) (num24 - (size2.Height / 2)));
                        }
                        if (this.labelsPosition == SliderElementsPosition.Internal)
                        {
                            g.DrawString(str2, this.Font, new SolidBrush(color4), (float) ((indicatorRectangle.X + (indicatorRectangle.Width / 2)) - (size2.Width / 2)), (float) (num24 - (size2.Height / 2)));
                        }
                    }
                }
            }
        }

        protected virtual void DrawSlider(Graphics g)
        {
        }

        protected double GetPercent(int value)
        {
            if (this.Maximum == this.Minimum)
            {
                return 0.0;
            }
            return ((value - this.Minimum) / ((double) (this.Maximum - this.Minimum)));
        }

        protected Color GetValueColor(int v)
        {
            switch (this.scaleColorMode)
            {
                case PerpetuumSoft.Widgets.ScaleColorMode.SingleColor:
                    return this.scaleColor;

                case PerpetuumSoft.Widgets.ScaleColorMode.Sections:
                    if (v >= this.dangerValue)
                    {
                        return this.dangerColor;
                    }
                    if (v >= this.warningValue)
                    {
                        return this.warningColor;
                    }
                    return this.scaleColor;
            }
            return this.scaleColor;
        }

        protected override int PointToValue(Point p)
        {
            double num;
            Rectangle indicatorRectangle = this.IndicatorRectangle;
            if (this.Orientation == PerpetuumSoft.Widgets.Orientation.Vertical)
            {
                if (p.Y >= indicatorRectangle.Bottom)
                {
                    return this.Minimum;
                }
                if (p.Y <= indicatorRectangle.Top)
                {
                    return this.Maximum;
                }
                num = ((double) ((indicatorRectangle.Y + indicatorRectangle.Height) - p.Y)) / ((double) indicatorRectangle.Height);
            }
            else
            {
                if (p.X <= indicatorRectangle.Left)
                {
                    return this.Minimum;
                }
                if (p.X >= indicatorRectangle.Right)
                {
                    return this.Maximum;
                }
                num = ((float) (p.X - indicatorRectangle.X)) / ((float) indicatorRectangle.Width);
            }
            return (((int) (num * (this.Maximum - this.Minimum))) + this.Minimum);
        }

        protected virtual Point ValueToPoint(int value)
        {
            Rectangle indicatorRectangle = this.IndicatorRectangle;
            if (this.Orientation == PerpetuumSoft.Widgets.Orientation.Vertical)
            {
                int num = (int) (this.GetPercent(base.Value) * indicatorRectangle.Height);
                return new Point(indicatorRectangle.X + (indicatorRectangle.Width / 2), (indicatorRectangle.Y + indicatorRectangle.Height) - num);
            }
            int num2 = (int) (this.GetPercent(base.Value) * indicatorRectangle.Width);
            return new Point(indicatorRectangle.X + num2, indicatorRectangle.Y + (indicatorRectangle.Height / 2));
        }

        protected abstract int CenterLine { get; }

        [Description("Color of the scale ticks and numbers in the danger section"), DefaultValue(typeof(Color), "Red"), Category("Appearance")]
        public Color DangerColor
        {
            get
            {
                return this.dangerColor;
            }
            set
            {
                if (value != this.dangerColor)
                {
                    this.dangerColor = value;
                    base.Invalidate();
                }
            }
        }

        [Description("Start value of the danger section"), Category("Appearance"), Editor(typeof(ValueEditor), typeof(UITypeEditor)), DefaultValue(80)]
        public int DangerValue
        {
            get
            {
                return this.dangerValue;
            }
            set
            {
                if (value != this.dangerValue)
                {
                    this.dangerValue = value;
                    base.Invalidate();
                }
            }
        }

        protected override bool Editable
        {
            get
            {
                return !this.indicatorOnly;
            }
        }

        [Category("Behavior"), DefaultValue(false)]
        public bool IndicatorOnly
        {
            get
            {
                return this.indicatorOnly;
            }
            set
            {
                if (this.indicatorOnly != value)
                {
                    this.indicatorOnly = value;
                    if (value)
                    {
                        base.SetStyle(0x200, true);
                    }
                    else
                    {
                        base.SetStyle(0x200, false);
                    }
                }
            }
        }

        protected abstract Rectangle IndicatorRectangle { get; }

        [Description("Labels text"), Category("Appearance")]
        public string[] Labels
        {
            get
            {
                return this.labels;
            }
            set
            {
                this.labels = value;
                base.Invalidate();
            }
        }

        [Description("Number of the text  labels on the scale"), DefaultValue(5), Category("Appearance")]
        public int LabelsCount
        {
            get
            {
                return this.labelsCount;
            }
            set
            {
                if (value != this.labelsCount)
                {
                    this.labelsCount = value;
                    base.Invalidate();
                }
            }
        }

        [DefaultValue(3), Description("Position of the text  labels on the scale"), Category("Appearance")]
        public SliderElementsPosition LabelsPosition
        {
            get
            {
                return this.labelsPosition;
            }
            set
            {
                if (this.labelsPosition != value)
                {
                    this.labelsPosition = value;
                    base.Invalidate();
                }
            }
        }

        [DefaultValue(1), Description("Control orientation"), Category("Appearance")]
        public virtual PerpetuumSoft.Widgets.Orientation Orientation
        {
            get
            {
                return this.orientation;
            }
            set
            {
                if (this.orientation != value)
                {
                    this.orientation = value;
                    base.Invalidate();
                }
            }
        }

        [Category("Appearance"), Description("Color of the scale ticks and numbers"), DefaultValue(typeof(Color), "Black")]
        public Color ScaleColor
        {
            get
            {
                return this.scaleColor;
            }
            set
            {
                if (value != this.scaleColor)
                {
                    this.scaleColor = value;
                    base.Invalidate();
                }
            }
        }

        [DefaultValue(1), Description("Scale appearance mode"), Category("Appearance")]
        public PerpetuumSoft.Widgets.ScaleColorMode ScaleColorMode
        {
            get
            {
                return this.scaleColorMode;
            }
            set
            {
                if (value != this.scaleColorMode)
                {
                    this.scaleColorMode = value;
                    base.Invalidate();
                }
            }
        }

        [DefaultValue(10), Category("Appearance"), Description("Number of divisions on the scale")]
        public int TicksCount
        {
            get
            {
                return this.ticksCount;
            }
            set
            {
                if (value != this.ticksCount)
                {
                    this.ticksCount = value;
                    base.Invalidate();
                }
            }
        }

        [Category("Appearance"), DefaultValue(8), Description("Lenght of the scale ticks")]
        public int TicksLenght
        {
            get
            {
                return this.ticksLenght;
            }
            set
            {
                if (value != this.ticksLenght)
                {
                    this.ticksLenght = value;
                    base.Invalidate();
                }
            }
        }

        [Description("Position of the ticks on the scale"), DefaultValue(3), Category("Appearance")]
        public SliderElementsPosition TicksPosition
        {
            get
            {
                return this.ticksPosition;
            }
            set
            {
                if (this.ticksPosition != value)
                {
                    this.ticksPosition = value;
                    base.Invalidate();
                }
            }
        }

        [Description("Number of subdivisions in each division on the scale"), Category("Appearance"), DefaultValue(5)]
        public int TicksSubDivisionsCount
        {
            get
            {
                return this.ticksSubDivisionsCount;
            }
            set
            {
                if (value != this.ticksSubDivisionsCount)
                {
                    this.ticksSubDivisionsCount = value;
                    base.Invalidate();
                }
            }
        }

        [Description("Color of the scale ticks and numbers in the warning section"), Category("Appearance"), DefaultValue(typeof(Color), "SaddleBrown")]
        public Color WarningColor
        {
            get
            {
                return this.warningColor;
            }
            set
            {
                if (value != this.warningColor)
                {
                    this.warningColor = value;
                    base.Invalidate();
                }
            }
        }

        [Category("Appearance"), DefaultValue(50), Editor(typeof(ValueEditor), typeof(UITypeEditor)), Description("Start value of the warning section")]
        public int WarningValue
        {
            get
            {
                return this.warningValue;
            }
            set
            {
                if (value != this.warningValue)
                {
                    this.warningValue = value;
                    base.Invalidate();
                }
            }
        }
    }
}
