namespace PerpetuumSoft.Widgets
{
    using PerpetuumSoft.Widgets.Licensing;
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Runtime.CompilerServices;

    [LicenseProvider(typeof(WidgetsLicenseProvider)), DefaultProperty("Value"), ToolboxBitmap(typeof(Odometer))]
    public class Odometer : InstrumentationControl
    {
        private Color firstDigitBackColor = Color.Red;
        private Color firstDigitForeColor = Color.White;
        private bool showGradient = true;
        private OdometerStyle style = OdometerStyle.Mechanic;
        private float value = 0f;

        [Category("Action"), Description("Occurs when Value of the control changed")]
        public event EventHandler ValueChanged;

        protected override void Draw(Graphics g, Rectangle r)
        {
            base.Draw(g, r);
            this.DrawNumber(g);
            if (this.showGradient)
            {
                Rectangle workRectangle = this.WorkRectangle;
                LinearGradientBrush brush = new LinearGradientBrush(workRectangle, Color.FromArgb(0x80, 0, 0, 0), Color.FromArgb(0x80, 0, 0, 0), 1);
                ColorBlend blend = new ColorBlend(3);
                blend.get_Positions()[0] = 0f;
                blend.get_Positions()[1] = 0.4f;
                blend.get_Positions()[2] = 1f;
                blend.get_Colors()[0] = Color.FromArgb(0x80, 0, 0, 0);
                blend.get_Colors()[1] = Color.Transparent;
                blend.get_Colors()[2] = Color.FromArgb(0x80, 0, 0, 0);
                brush.set_InterpolationColors(blend);
                g.FillRectangle(brush, workRectangle);
                brush.Dispose();
            }
        }

        private void DrawDigit(Graphics g, Rectangle rect, Color color, Color digitColor, int digit, float delta)
        {
            GraphicsContainer container = g.BeginContainer();
            g.IntersectClip(rect);
            g.FillRectangle(new SolidBrush(color), rect);
            StringFormat format = new StringFormat();
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;
            int num = (digit == 9) ? 0 : (digit + 1);
            float height = g.MeasureString("8", this.Font).Height;
            Rectangle layoutRectangle = rect;
            layoutRectangle.Y += ((int) height) - ((int) (height * delta));
            if (this.style == OdometerStyle.Mechanic)
            {
                rect.Y -= (int) (height * delta);
                g.DrawString(digit.ToString(), this.Font, new SolidBrush(digitColor), rect, format);
                if (delta != 0f)
                {
                    g.DrawString(num.ToString(), this.Font, new SolidBrush(digitColor), layoutRectangle, format);
                }
            }
            else
            {
                Color color2 = digitColor;
                if (delta >= 0.6f)
                {
                    color2 = GraphicsUtils.TransparentColor(digitColor, 1f - ((delta - 0.6f) * 2f));
                }
                g.DrawString(digit.ToString(), this.Font, new SolidBrush(color2), rect, format);
                if (delta != 0f)
                {
                    Color color3 = GraphicsUtils.TransparentColor(digitColor, delta);
                    g.DrawString(num.ToString(), this.Font, new SolidBrush(color3), layoutRectangle, format);
                }
            }
            g.EndContainer(container);
        }

        private void DrawNumber(Graphics g)
        {
            Rectangle workRectangle = this.WorkRectangle;
            Size size = Size.Ceiling(g.MeasureString("8", this.Font));
            int num = workRectangle.Width / (size.Width + 2);
            int[] numArray = new int[num];
            string format = string.Empty;
            for (int i = 0; i < num; i++)
            {
                format = format + "0";
            }
            string str2 = Math.Floor((double) this.value).ToString(format);
            for (int j = 0; j < num; j++)
            {
                numArray[j] = short.Parse(str2[j].ToString());
            }
            for (int k = 0; k < num; k++)
            {
                int index = (num - k) - 1;
                int digit = numArray[index];
                Rectangle rect = new Rectangle((workRectangle.X + workRectangle.Width) - ((k + 1) * (size.Width + 2)), workRectangle.Y, size.Width, workRectangle.Height);
                float delta = 0f;
                if (k == 0)
                {
                    delta = this.value - ((float) Math.Floor((double) this.value));
                }
                else
                {
                    bool flag = true;
                    for (int m = index + 1; m <= (num - 1); m++)
                    {
                        if (numArray[m] != 9)
                        {
                            flag = false;
                        }
                    }
                    if (flag)
                    {
                        delta = this.value - ((float) Math.Floor((double) this.value));
                    }
                }
                Color color = (k == 0) ? this.FirstDigitBackColor : this.BackColor;
                Color digitColor = (k == 0) ? this.FirstDigitForeColor : this.ForeColor;
                this.DrawDigit(g, rect, color, digitColor, digit, delta);
            }
        }

        protected virtual void OnValueChanged(EventArgs e)
        {
            if (this.ValueChanged != null)
            {
                this.ValueChanged(this, e);
            }
        }

        [DefaultValue(typeof(Color), "Red"), Description("Back Color of the first digit"), Category("Appearance")]
        public Color FirstDigitBackColor
        {
            get
            {
                return this.firstDigitBackColor;
            }
            set
            {
                if (this.firstDigitBackColor != value)
                {
                    this.firstDigitBackColor = value;
                    base.Invalidate();
                }
            }
        }

        [Category("Appearance"), Description("Fore Color of the first digit"), DefaultValue(typeof(Color), "White")]
        public Color FirstDigitForeColor
        {
            get
            {
                return this.firstDigitForeColor;
            }
            set
            {
                if (this.firstDigitForeColor != value)
                {
                    this.firstDigitForeColor = value;
                    base.Invalidate();
                }
            }
        }

        [Category("Appearance"), Description("Gets or sets whether control should use gradient background"), DefaultValue(false)]
        public bool ShowGradient
        {
            get
            {
                return this.showGradient;
            }
            set
            {
                if (this.showGradient != value)
                {
                    this.showGradient = value;
                    base.Invalidate();
                }
            }
        }

        [Description("The odometer appearance style"), DefaultValue(0), Category("Appearance")]
        public OdometerStyle Style
        {
            get
            {
                return this.style;
            }
            set
            {
                if (this.style != value)
                {
                    this.style = value;
                    base.Invalidate();
                }
            }
        }

        [DefaultValue((float) 0f), Category("Behavior"), Description("The position of the marker")]
        public float Value
        {
            get
            {
                return this.value;
            }
            set
            {
                if (value != this.value)
                {
                    this.value = value;
                    this.OnValueChanged(EventArgs.Empty);
                    base.Invalidate();
                }
            }
        }
    }
}
