using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Mesnac.Controls.ChemicalWeighing
{
    /// <summary>一个传送带的控件</summary>
    [Description("传送带控件,支持正反方向设置,支持转速设置,颜色设置")]
    public class HslConveyer : UserControl
    {
        private StringFormat sf = (StringFormat)null;
        private float moveSpeed = 0.3f;
        private float startAngle = 0.0f;
        private float startOffect = 0.0f;
        private Timer timer = (Timer)null;
        private bool isConveyerActive = false;
        private float circularRadius = 20f;
        private HslConveyerStyle conveyerStyle = HslConveyerStyle.Horizontal;
        /// <summary>必需的设计器变量。</summary>
        private IContainer components = (IContainer)null;

        /// <summary>实例化一个传送带的控件对象</summary>
        public HslConveyer()
        {
            this.InitializeComponent();
            this.sf = new StringFormat();
            this.sf.Alignment = StringAlignment.Center;
            this.sf.LineAlignment = StringAlignment.Center;
            this.SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            base.ForeColor = Color.FromArgb(142, 196, 216);
            this.timer = new Timer();
            this.timer.Interval = 50;
            this.timer.Tick += new EventHandler(this.Timer_Tick);
            this.timer.Start();
        }

        /// <summary>获取或设置控件的背景色</summary>
        [Browsable(true)]
        [Description("获取或设置控件的背景色")]
        [Category("HslControls")]
        [DefaultValue(typeof(Color), "Transparent")]
        [EditorBrowsable(EditorBrowsableState.Always)]
        public override Color BackColor
        {
            get => base.BackColor;
            set => base.BackColor = value;
        }

        /// <summary>获取或设置当前控件的文本</summary>
        [Browsable(true)]
        [Description("获取或设置当前控件的文本")]
        [Category("HslControls")]
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Bindable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override string Text
        {
            get => base.Text;
            set
            {
                base.Text = value;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置控件的背景色</summary>
        [Browsable(true)]
        [Description("获取或设置控件的前景色")]
        [Category("HslControls")]
        [DefaultValue(typeof(Color), "[142, 196, 216]")]
        [EditorBrowsable(EditorBrowsableState.Always)]
        public override Color ForeColor
        {
            get => base.ForeColor;
            set
            {
                base.ForeColor = value;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置传送带流动的速度,0为静止,正数为正向流动,负数为反向流动,一般情况值范围为 -9 ~ 9</summary>
        [Browsable(true)]
        [Description("获取或设置传送带流动的速度,0为静止,正数为正向流动,负数为反向流动,一般情况值范围为 -9 ~ 9")]
        [Category("HslControls")]
        [DefaultValue(0.3f)]
        public virtual float MoveSpeed
        {
            get => this.moveSpeed;
            set
            {
                this.moveSpeed = value;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置管道线是否激活液体显示</summary>
        [Browsable(true)]
        [Description("获取或设置管道线是否激活液体显示")]
        [Category("HslControls")]
        [DefaultValue(false)]
        public virtual bool ConveyerActive
        {
            get => this.isConveyerActive;
            set
            {
                this.isConveyerActive = value;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置两侧的圆圈的半径,当且仅当ConveyerStyle属性不为Horizontal枚举时成立</summary>
        [Browsable(true)]
        [Description("获取或设置两侧的圆圈的半径,当且仅当ConveyerStyle属性不为Horizontal枚举时成立")]
        [Category("HslControls")]
        [DefaultValue(HslConveyerStyle.Horizontal)]
        public virtual float CircularRadius
        {
            get => this.circularRadius;
            set
            {
                if ((double)value > (double)(this.Width / 2) || (double)value > (double)(this.Height / 2))
                    return;
                this.circularRadius = value;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置传送带的样式,水平,还是上坡,还是下坡</summary>
        [Browsable(true)]
        [Description("获取或设置传送带的样式,水平,还是上坡,还是下坡")]
        [Category("HslControls")]
        [DefaultValue(HslConveyerStyle.Horizontal)]
        public virtual HslConveyerStyle ConveyerStyle
        {
            get => this.conveyerStyle;
            set
            {
                this.conveyerStyle = value;
                this.Invalidate();
            }
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            if ((double)this.moveSpeed == 0.0)
                return;
            if (this.isConveyerActive)
            {
                this.startOffect -= this.moveSpeed;
                if ((double)this.startOffect <= -10.0 || (double)this.startOffect >= 10.0)
                    this.startOffect = 0.0f;
            }
            this.startAngle += (float)((double)this.moveSpeed * 180.0 / Math.PI / 10.0);
            while ((double)this.startAngle < -360.0)
                this.startAngle += 360f;
            while ((double)this.startAngle >= 360.0)
                this.startAngle -= 360f;
            this.Invalidate();
        }

        /// <summary>重绘控件的界面信息</summary>
        /// <param name="e">事件</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
            this.PaintHslControls(e.Graphics, this.Width, this.Height);
            base.OnPaint(e);
        }

        /// <inheritdoc cref="M:HslControls.HslArrow.PaintHslControls(System.Drawing.Graphics,System.Single,System.Single)" />
        public void PaintHslControls(Graphics g, int width, int height)
        {
           
            int margin = 5;
            int offect = 5;
            if (this.conveyerStyle == HslConveyerStyle.Horizontal)
                this.PaintMain(g, (float)width, (float)height, (float)margin, (float)offect);
            else if (this.conveyerStyle == HslConveyerStyle.Upslope)
            {
                PointF pointF1 = new PointF((float)(margin + offect) + this.circularRadius, (float)(height - 1 - margin - offect) - this.circularRadius);
                PointF pointF2 = new PointF((float)(width - margin - offect - 1) - this.circularRadius, (float)(margin + offect) + this.circularRadius);
                float num1 = (float)Math.Sqrt(Math.Pow((double)pointF2.Y - (double)pointF1.Y, 2.0) + Math.Pow((double)pointF2.X - (double)pointF1.X, 2.0));
                float num2 = (float)(Math.Acos(((double)pointF2.X - (double)pointF1.X) / (double)num1) * 180.0 / Math.PI);
                g.TranslateTransform(pointF1.X, pointF1.Y);
                g.RotateTransform(-num2);
                g.TranslateTransform((float)(-margin - offect) - this.circularRadius, (float)(-margin - offect) - this.circularRadius);
                this.PaintMain(g, (float)((double)num1 + (double)(2 * margin) + (double)(2 * offect) + 2.0 * (double)this.circularRadius), (float)(2 * margin + 2 * offect) + 2f * this.circularRadius, (float)margin, (float)offect);
                g.ResetTransform();
            }
            else
            {
                PointF pointF3 = new PointF((float)(margin + offect) + this.circularRadius, (float)(margin + offect) + this.circularRadius);
                PointF pointF4 = new PointF((float)(width - margin - offect - 1) - this.circularRadius, (float)(height - 1 - margin - offect) - this.circularRadius);
                float num = (float)Math.Sqrt(Math.Pow((double)pointF4.Y - (double)pointF3.Y, 2.0) + Math.Pow((double)pointF4.X - (double)pointF3.X, 2.0));
                float angle = (float)(Math.Acos(((double)pointF4.X - (double)pointF3.X) / (double)num) * 180.0 / Math.PI);
                g.TranslateTransform(pointF3.X, pointF3.Y);
                g.RotateTransform(angle);
                g.TranslateTransform((float)(-margin - offect) - this.circularRadius, (float)(-margin - offect) - this.circularRadius);
                this.PaintMain(g, (float)((double)num + (double)(2 * margin) + (double)(2 * offect) + 2.0 * (double)this.circularRadius), (float)(2 * margin + 2 * offect) + 2f * this.circularRadius, (float)margin, (float)offect);
                g.ResetTransform();
            }
        }

        private void PaintMain(Graphics g, float width, float height, float margin, float offect)
        {
            float num1 = (float)(((double)height - (double)margin * 2.0 - (double)offect * 2.0) / 2.0);
            float startAngle = this.startAngle;
            Pen pen1 = new Pen(this.ForeColor, 1f);
            Pen pen2 = new Pen(this.ForeColor, (double)num1 > 100.0 ? 7f : ((double)num1 > 20.0 ? 5f : ((double)num1 > 5.0 ? 3f : 1f)));
            pen2.StartCap = LineCap.Round;
            pen2.EndCap = LineCap.Round;
            Brush brush = (Brush)new SolidBrush(this.ForeColor);
            GraphicsPath path = new GraphicsPath();
            path.AddArc(margin, margin, (float)((double)num1 * 2.0 + (double)offect * 2.0), (float)((double)num1 * 2.0 + (double)offect * 2.0), 90f, 180f);
            path.AddLine(margin + offect + num1, margin, (float)((double)width - (double)margin - (double)offect - (double)num1 - 1.0), margin);
            path.AddArc((float)((double)width - (double)margin - (double)num1 * 2.0 - (double)offect * 2.0), margin, (float)((double)num1 * 2.0 + (double)offect * 2.0), (float)((double)num1 * 2.0 + (double)offect * 2.0), -90f, 180f);
            path.CloseFigure();
            g.DrawPath(pen1, path);
            g.DrawEllipse(pen1, margin + offect, margin + offect, num1 * 2f, num1 * 2f);
            g.DrawEllipse(pen1, (float)((double)width - (double)margin - (double)num1 * 2.0) - offect, margin + offect, num1 * 2f, num1 * 2f);
            float num2 = (float)Math.Sqrt(2.0 * (double)offect * (double)num1 + (double)offect * (double)offect);
            float num3 = (float)(Math.Asin((double)num1 / ((double)num1 + (double)offect)) * 180.0 / Math.PI);
            path.Reset();
            path.AddArc(margin, margin, (float)((double)num1 * 2.0 + (double)offect * 2.0), (float)((double)num1 * 2.0 + (double)offect * 2.0), -num3, num3 * 2f);
            path.AddLine(margin + offect + num1 + num2, height - margin - offect, (float)((double)width - (double)margin - (double)offect - (double)num1 - 1.0) - num2, height - margin - offect);
            path.AddArc((float)((double)width - (double)margin - (double)num1 * 2.0 - (double)offect * 2.0), margin, (float)((double)num1 * 2.0 + (double)offect * 2.0), (float)((double)num1 * 2.0 + (double)offect * 2.0), 180f - num3, num3 * 2f);
            path.CloseFigure();
            g.DrawPath(pen1, path);
            g.TranslateTransform(margin + offect + num1, margin + offect + num1);
            g.RotateTransform(startAngle);
            g.DrawLine(pen2, (float)(-(double)num1 / 2.0), 0.0f, num1 / 2f, 0.0f);
            g.DrawLine(pen2, 0.0f, (float)(-(double)num1 / 2.0), 0.0f, num1 / 2f);
            g.RotateTransform(-startAngle);
            g.TranslateTransform(-margin - offect - num1, -margin - offect - num1);
            g.TranslateTransform(width - margin - num1 - offect, margin + offect + num1);
            g.RotateTransform(startAngle);
            g.DrawLine(pen2, (float)(-(double)num1 / 2.0), 0.0f, num1 / 2f, 0.0f);
            g.DrawLine(pen2, 0.0f, (float)(-(double)num1 / 2.0), 0.0f, num1 / 2f);
            g.RotateTransform(-startAngle);
            g.TranslateTransform(-width + margin + num1 + offect, -margin - offect - num1);
            if (this.isConveyerActive)
            {
                using (Pen pen3 = new Pen(this.ForeColor, 5f))
                {
                    pen3.DashStyle = DashStyle.Custom;
                    pen3.DashPattern = new float[2] { 5f, 5f };
                    pen3.DashOffset = this.startOffect;
                    path.Reset();
                    path.AddArc(margin + offect / 2f, margin + offect / 2f, num1 * 2f + offect, num1 * 2f + offect, 90f, 180f);
                    path.AddLine((float)((double)margin + (double)offect + (double)num1 + 1.0), margin + offect / 2f, (float)((double)width - (double)margin - (double)offect - (double)num1 - 2.0), margin + offect / 2f);
                    path.AddArc((float)((double)width - (double)margin - (double)num1 * 2.0 - (double)offect * 2.0 + (double)offect / 2.0), margin + offect / 2f, num1 * 2f + offect, num1 * 2f + offect, -90f, 180f);
                    path.CloseFigure();
                    g.DrawPath(pen3, path);
                }
            }
            g.DrawString(this.Text, this.Font, brush, new RectangleF(0.0f, 0.0f, width, height), this.sf);
            path.Dispose();
            pen1.Dispose();
            pen2.Dispose();
            brush.Dispose();
        }

        /// <summary>清理所有正在使用的资源。</summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && this.components != null)
                this.components.Dispose();
            base.Dispose(disposing);
        }

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.SuspendLayout();
            this.AutoScaleMode = AutoScaleMode.None;
            this.BackColor = Color.Transparent;
            this.Name = nameof(HslConveyer);
            this.Size = new Size(461, 61);
            this.ResumeLayout(false);
        }
    }
}