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

    [LicenseProvider(typeof(WidgetsLicenseProvider)), ToolboxBitmap(typeof(CircularGauge))]
    public class CircularGauge : ValuePresenter
    {
        private Color dangerColor = Color.Red;
        private int dangerValue = 70;
        private Color dialColor = Color.White;
        private int largeTickFrequency = 10;
        private int numberFrequency = 10;
        private Color pointerColor = Color.Red;
        private bool showGradient = false;
        private bool showNumbers = true;
        private int smallTickFrequency = 2;
        private int totalAngle = 270;

        protected override void Draw(Graphics g, Rectangle r)
        {
            base.Draw(g, r);
            Rectangle workRectangle = this.WorkRectangle;
            using (Pen pen = new Pen(this.ForeColor))
            {
                using (Pen pen2 = new Pen(this.dangerColor))
                {
                    Brush brush;
                    if (this.ShowGradient)
                    {
                        brush = new LinearGradientBrush(workRectangle, GraphicsUtils.ScaleColor(this.dialColor, 0.5f), this.dialColor, 1);
                    }
                    else
                    {
                        brush = new SolidBrush(this.dialColor);
                    }
                    using (Brush brush2 = new SolidBrush(this.ForeColor))
                    {
                        g.FillEllipse(brush, workRectangle);
                        Point center = this.Center;
                        int num = (int) (this.Radius * 0.8f);
                        float num2 = ((float) (base.Value - this.Minimum)) / (this.Maximum - this.Minimum);
                        float angle = num2 * this.totalAngle;
                        if (this.Text != "")
                        {
                            g.DrawString(this.Text, this.Font, brush2, (PointF) new Point(center.X - ((int) (g.MeasureString(this.Text, this.Font).Width / 2f)), (center.Y - 15) - (this.Font.get_Height() / 2)));
                        }
                        this.DrawPointer(g, center, angle, num * 0.8f);
                        int num4 = (int) (num * 0.7f);
                        int num5 = num4 + 3;
                        int num6 = num5 + 6;
                        for (int i = this.Minimum; i <= this.Maximum; i += this.smallTickFrequency)
                        {
                            num2 = ((float) (i - this.Minimum)) / (this.Maximum - this.Minimum);
                            float num8 = num2 * this.totalAngle;
                            float num9 = (((float) this.totalAngle) / 2f) - num8;
                            double num10 = center.X - (Math.Sin((num9 / 180f) * 3.1415926535897931) * num4);
                            double num11 = center.Y - (Math.Cos((num9 / 180f) * 3.1415926535897931) * num4);
                            double num12 = num5;
                            if ((i % this.largeTickFrequency) == 0)
                            {
                                num12 = num6;
                            }
                            if (this.showNumbers && ((i % this.numberFrequency) == 0))
                            {
                                int num13 = num6 + this.Font.get_Height();
                                double num14 = center.X - (Math.Sin((num9 / 180f) * 3.1415926535897931) * num13);
                                double num15 = center.Y - (Math.Cos((num9 / 180f) * 3.1415926535897931) * num13);
                                string text = base.FormatValue(i);
                                SizeF ef = g.MeasureString(text, this.Font);
                                num14 -= ef.Width / 2f;
                                num15 -= ef.Height / 2f;
                                g.DrawString(text, this.Font, brush2, (PointF) new Point((int) num14, (int) num15));
                            }
                            double num16 = center.X - (Math.Sin((num9 / 180f) * 3.1415926535897931) * num12);
                            double num17 = center.Y - (Math.Cos((num9 / 180f) * 3.1415926535897931) * num12);
                            PointF tf = new PointF((float) num10, (float) num11);
                            PointF tf2 = new PointF((float) num16, (float) num17);
                            if (i < this.dangerValue)
                            {
                                g.DrawLine(pen, tf, tf2);
                            }
                            else
                            {
                                g.DrawLine(pen2, tf, tf2);
                            }
                        }
                        g.Flush();
                    }
                    brush.Dispose();
                }
            }
        }

        private void DrawPointer(Graphics g, Point p, float angle, float rad)
        {
            float num = (((float) this.totalAngle) / 2f) - angle;
            double num2 = p.X - (Math.Sin((num / 180f) * 3.1415926535897931) * rad);
            double num3 = p.Y - (Math.Cos((num / 180f) * 3.1415926535897931) * rad);
            Point point = new Point((int) num2, (int) num3);
            g.DrawLine(new Pen(this.pointerColor), p, point);
        }

        protected override void OnTextChanged(EventArgs e)
        {
            base.Invalidate();
            base.OnTextChanged(e);
        }

        private Point Center
        {
            get
            {
                Rectangle workRectangle = this.WorkRectangle;
                return new Point((workRectangle.Left + workRectangle.Right) / 2, (workRectangle.Bottom + workRectangle.Top) / 2);
            }
        }

        [Description("Danger color"), DefaultValue(typeof(Color), "Red"), Category("Appearance")]
        public Color DangerColor
        {
            get
            {
                return this.dangerColor;
            }
            set
            {
                if (this.dangerColor != value)
                {
                    this.dangerColor = value;
                    base.Invalidate();
                }
            }
        }

        [Category("Behavior"), Description("Danger Value"), DefaultValue(70)]
        public int DangerValue
        {
            get
            {
                return this.dangerValue;
            }
            set
            {
                if (this.dangerValue != value)
                {
                    this.dangerValue = value;
                    base.Invalidate();
                }
            }
        }

        protected override Size DefaultSize
        {
            get
            {
                return new Size(0xa8, 0xa8);
            }
        }

        [DefaultValue(typeof(Color), "White"), Category("Appearance"), Description("Color of the dial")]
        public Color DialColor
        {
            get
            {
                return this.dialColor;
            }
            set
            {
                if (this.dialColor != value)
                {
                    this.dialColor = value;
                    base.Invalidate();
                }
            }
        }

        [Description("Define frequency of large ticks"), Category("Appearance"), DefaultValue(10)]
        public int LargeTickFrequency
        {
            get
            {
                return this.largeTickFrequency;
            }
            set
            {
                if (this.largeTickFrequency != value)
                {
                    this.largeTickFrequency = value;
                    base.Invalidate();
                }
            }
        }

        [DefaultValue(10), Description("Define frequency of numbers"), Category("Appearance")]
        public int NumberFrequency
        {
            get
            {
                return this.numberFrequency;
            }
            set
            {
                if (this.numberFrequency != value)
                {
                    this.numberFrequency = value;
                    base.Invalidate();
                }
            }
        }

        [Category("Appearance"), Description("Color of the pointer"), DefaultValue(typeof(Color), "Red")]
        public Color PointerColor
        {
            get
            {
                return this.pointerColor;
            }
            set
            {
                if (this.pointerColor != value)
                {
                    this.pointerColor = value;
                    base.Invalidate();
                }
            }
        }

        private int Radius
        {
            get
            {
                Rectangle workRectangle = this.WorkRectangle;
                return Math.Min((int) (workRectangle.Height / 2), (int) (workRectangle.Width / 2));
            }
        }

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

        [Category("Appearance"), DefaultValue(true), Description("Indicate if the control paints scale numbers")]
        public bool ShowNumbers
        {
            get
            {
                return this.showNumbers;
            }
            set
            {
                if (this.showNumbers != value)
                {
                    this.showNumbers = value;
                    base.Invalidate();
                }
            }
        }

        [DefaultValue(2), Category("Appearance"), Description("Define frequency of small ticks")]
        public int SmallTickFrequency
        {
            get
            {
                return this.smallTickFrequency;
            }
            set
            {
                if (this.smallTickFrequency != value)
                {
                    this.smallTickFrequency = value;
                    base.Invalidate();
                }
            }
        }

        [DefaultValue(270), Description("Angle behind minimum and maximum positions"), Category("Appearance")]
        public int TotalAngle
        {
            get
            {
                return this.totalAngle;
            }
            set
            {
                if (this.totalAngle != value)
                {
                    this.totalAngle = value;
                    base.Invalidate();
                }
            }
        }
    }
}
