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 HslPipeLineThree : UserControl
    {
        private ArrowDirection arrowDirection = ArrowDirection.Down;
        private Color centerColor = Color.LightGray;
        private Color edgeColor = Color.DimGray;
        private Pen edgePen = new Pen(Color.DimGray, 1f);
        private bool isPipeLineActive1 = false;
        private bool isPipeLineActive2 = false;
        private bool isPipeLineActive3 = false;
        private int pipeLineWidth = 3;
        private Color colorPipeLineCenter = Color.DodgerBlue;
        private float moveSpeed1 = 0.0f;
        private float moveSpeed2 = 0.0f;
        private float moveSpeed3 = 0.0f;
        private float startOffect1 = 0.0f;
        private float startOffect2 = 0.0f;
        private float startOffect3 = 0.0f;
        private Timer timer = (Timer)null;
        private int pipeWidth = 30;
        private float antLength = 5f;
        /// <summary>必需的设计器变量。</summary>
        private IContainer components = (IContainer)null;

        /// <summary>实例化一个默认的管道线对象</summary>
        public HslPipeLineThree()
        {
            this.InitializeComponent();
            this.SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.timer = new Timer();
            this.timer.Interval = 50;
            this.timer.Tick += new EventHandler(this.Timer_Tick);
            this.timer.Start();
        }

        /// <inheritdoc />
        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
            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)
        {
           
            if (this.arrowDirection == ArrowDirection.Down)
                this.PaintMain(g, width, height);
            else if (this.arrowDirection == ArrowDirection.Right)
            {
                g.TranslateTransform(0.0f, (float)height);
                g.RotateTransform(-90f);
                this.PaintMain(g, height, width);
                g.RotateTransform(90f);
                g.TranslateTransform(0.0f, (float)-height);
            }
            else if (this.arrowDirection == ArrowDirection.Left)
            {
                g.TranslateTransform((float)width, 0.0f);
                g.RotateTransform(90f);
                this.PaintMain(g, height, width);
                g.RotateTransform(-90f);
                g.TranslateTransform((float)-width, 0.0f);
            }
            else
            {
                g.RotateTransform(-180f);
                g.TranslateTransform((float)-width, (float)-height);
                this.PaintMain(g, width, height);
                g.TranslateTransform((float)width, (float)height);
                g.RotateTransform(180f);
            }
        }

        private void PaintMain(Graphics g, int width, int height)
        {
            ColorBlend colorBlend = new ColorBlend();
            colorBlend.Positions = new float[3] { 0.0f, 0.5f, 1f };
            colorBlend.Colors = new Color[3]
            {
        this.edgeColor,
        this.centerColor,
        this.edgeColor
            };
            LinearGradientBrush linearGradientBrush1 = new LinearGradientBrush(new Point(0, 0), new Point(0, this.pipeWidth - 1), this.edgeColor, this.centerColor);
            linearGradientBrush1.InterpolationColors = colorBlend;
            g.FillRectangle((Brush)linearGradientBrush1, new Rectangle(0, 0, width, this.pipeWidth - 1));
            g.DrawLine(this.edgePen, 0, 0, width, 0);
            g.DrawLine(this.edgePen, 0, this.pipeWidth - 1, width, this.pipeWidth - 1);
            linearGradientBrush1.Dispose();
            LinearGradientBrush linearGradientBrush2 = new LinearGradientBrush(new Point((width - this.pipeWidth) / 2, 0), new Point((width + this.pipeWidth) / 2, 0), this.edgeColor, this.centerColor);
            linearGradientBrush2.InterpolationColors = colorBlend;
            g.FillPolygon((Brush)linearGradientBrush2, new PointF[5]
            {
        new PointF((float) (width / 2), (float) (this.pipeWidth / 2)),
        new PointF((float) ((width - this.pipeWidth) / 2), (float) this.pipeWidth),
        new PointF((float) ((width - this.pipeWidth) / 2), (float) height),
        new PointF((float) ((width + this.pipeWidth) / 2 - 1), (float) height),
        new PointF((float) ((width + this.pipeWidth) / 2 - 1), (float) this.pipeWidth)
            });
            linearGradientBrush2.Dispose();
            g.DrawLine(this.edgePen, (width - this.pipeWidth) / 2, this.pipeWidth, (width - this.pipeWidth) / 2, height);
            g.DrawLine(this.edgePen, (width + this.pipeWidth) / 2 - 1, height, (width + this.pipeWidth) / 2 - 1, this.pipeWidth);
            GraphicsPath path1 = new GraphicsPath(FillMode.Alternate);
            GraphicsPath path2 = new GraphicsPath(FillMode.Alternate);
            GraphicsPath path3 = new GraphicsPath(FillMode.Alternate);
            if (this.isPipeLineActive1)
                path1.AddLine(0, this.pipeWidth / 2, width, this.pipeWidth / 2);
            if (this.isPipeLineActive2)
            {
                path2.AddLine(0, this.pipeWidth / 2, (width - this.pipeWidth) / 2, this.pipeWidth / 2);
                path2.AddArc(new Rectangle(width / 2 - this.pipeWidth, this.pipeWidth / 2, this.pipeWidth, this.pipeWidth), 270f, 90f);
                path2.AddLine(width / 2, this.pipeWidth, width / 2, height);
            }
            if (this.isPipeLineActive3)
            {
                path3.AddLine(width / 2, height, width / 2, this.pipeWidth);
                path3.AddArc(new Rectangle(width / 2, this.pipeWidth / 2, this.pipeWidth, this.pipeWidth), 180f, 90f);
                path3.AddLine((width + this.pipeWidth) / 2, this.pipeWidth / 2, width, this.pipeWidth / 2);
            }
            using (Pen pen = new Pen(this.colorPipeLineCenter, (float)this.pipeLineWidth))
            {
                pen.DashStyle = DashStyle.Custom;
                pen.DashPattern = new float[2] { this.antLength, 5f };
                pen.DashOffset = this.startOffect1;
                g.DrawPath(pen, path1);
                pen.DashOffset = this.startOffect2;
                g.DrawPath(pen, path2);
                pen.DashOffset = this.startOffect3;
                g.DrawPath(pen, path3);
            }
            path1.Dispose();
            path2.Dispose();
            path3.Dispose();
        }

        private void PaintRectangleBorder(
          Graphics g,
          Brush brush,
          Pen pen,
          Rectangle rectangle,
          bool left,
          bool right,
          bool up,
          bool down)
        {
            g.FillRectangle(brush, rectangle);
            if (left)
                g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X, rectangle.Y + rectangle.Height - 1);
            if (up)
                g.DrawLine(pen, rectangle.X, rectangle.Y, rectangle.X + rectangle.Width - 1, rectangle.Y);
            if (right)
                g.DrawLine(pen, rectangle.X + rectangle.Width - 1, rectangle.Y, rectangle.X + rectangle.Width - 1, rectangle.Y + rectangle.Height - 1);
            if (!down)
                return;
            g.DrawLine(pen, rectangle.X, rectangle.Y + rectangle.Height - 1, rectangle.X + rectangle.Width - 1, rectangle.Y + rectangle.Height - 1);
        }

        private void PaintRectangleBorderUpDown(Graphics g, Brush brush, Pen pen, Rectangle rectangle) => this.PaintRectangleBorder(g, brush, pen, rectangle, false, false, true, true);

        private void Timer_Tick(object sender, EventArgs e)
        {
            if (!this.isPipeLineActive1 && !this.isPipeLineActive2 && !this.isPipeLineActive3 || (double)this.moveSpeed1 == 0.0 && (double)this.moveSpeed2 == 0.0 && (double)this.moveSpeed3 == 0.0)
                return;
            this.startOffect1 -= this.moveSpeed1;
            if ((double)this.startOffect1 <= -((double)this.antLength * 2.0) || (double)this.startOffect1 >= (double)this.antLength * 2.0)
                this.startOffect1 = 0.0f;
            this.startOffect2 -= this.moveSpeed2;
            if ((double)this.startOffect2 <= -((double)this.antLength * 2.0) || (double)this.startOffect2 >= (double)this.antLength * 2.0)
                this.startOffect2 = 0.0f;
            this.startOffect3 -= this.moveSpeed3;
            if ((double)this.startOffect3 <= -((double)this.antLength * 2.0) || (double)this.startOffect3 >= (double)this.antLength * 2.0)
                this.startOffect3 = 0.0f;
            this.Invalidate();
        }

        /// <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")]
        [DefaultValue(typeof(Color), "DimGray")]
        public Color EdgeColor
        {
            get => this.edgeColor;
            set
            {
                this.edgeColor = value;
                this.edgePen.Dispose();
                this.edgePen = new Pen(value, 1f);
                this.Invalidate();
            }
        }

        /// <summary>获取或设置管道控件的中心颜色</summary>
        [Browsable(true)]
        [Description("获取或设置管道控件的中心颜色")]
        [Category("HslControls")]
        [DefaultValue(typeof(Color), "LightGray")]
        public Color LineCenterColor
        {
            get => this.centerColor;
            set
            {
                this.centerColor = value;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置管道控件是否是横向的还是纵向的</summary>
        [Browsable(true)]
        [Description("获取或设置管道控件是否是横向的还是纵向的")]
        [Category("HslControls")]
        [DefaultValue(typeof(ArrowDirection), "Down")]
        public ArrowDirection PipeLineStyle
        {
            get => this.arrowDirection;
            set
            {
                this.arrowDirection = value;
                this.Invalidate();
            }
        }

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

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

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

        /// <summary>获取或设置管道1号线液体流动的速度,0为静止,正数为正向流动,负数为反向流动</summary>
        [Browsable(true)]
        [Description("获取或设置管道线液体流动的速度,0为静止,正数为正向流动,负数为反向流动")]
        [Category("HslControls")]
        [DefaultValue(0.0f)]
        public float MoveSpeed1
        {
            get => this.moveSpeed1;
            set
            {
                this.moveSpeed1 = value;
                this.startOffect1 = 0.0f;
                this.startOffect2 = 0.0f;
                this.startOffect3 = 0.0f;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置管道2号线液体流动的速度,0为静止,正数为正向流动,负数为反向流动</summary>
        [Browsable(true)]
        [Description("获取或设置管道线液体流动的速度,0为静止,正数为正向流动,负数为反向流动")]
        [Category("HslControls")]
        [DefaultValue(0.0f)]
        public float MoveSpeed2
        {
            get => this.moveSpeed2;
            set
            {
                this.moveSpeed2 = value;
                this.startOffect1 = 0.0f;
                this.startOffect2 = 0.0f;
                this.startOffect3 = 0.0f;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置管道3号线液体流动的速度,0为静止,正数为正向流动,负数为反向流动</summary>
        [Browsable(true)]
        [Description("获取或设置管道线液体流动的速度,0为静止,正数为正向流动,负数为反向流动")]
        [Category("HslControls")]
        [DefaultValue(0.0f)]
        public float MoveSpeed3
        {
            get => this.moveSpeed3;
            set
            {
                this.moveSpeed3 = value;
                this.startOffect1 = 0.0f;
                this.startOffect2 = 0.0f;
                this.startOffect3 = 0.0f;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置液体控制的定时器刷新的间隔,默认是50</summary>
        [Browsable(true)]
        [Description("获取或设置液体控制的定时器刷新的间隔,默认是50")]
        [Category("HslControls")]
        [DefaultValue(50)]
        public int TimerInterval
        {
            get => this.timer.Interval;
            set => this.timer.Interval = value;
        }

        /// <summary>获取或设置中间管道线的宽度信息,默认为3</summary>
        [Browsable(true)]
        [Description("获取或设置中间管道线的宽度信息,默认为3")]
        [Category("HslControls")]
        [DefaultValue(3)]
        public int PipeLineWidth
        {
            get => this.pipeLineWidth;
            set
            {
                this.pipeLineWidth = value;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置流动状态时管道控件的中心颜色</summary>
        [Browsable(true)]
        [Description("获取或设置流动状态时管道控件的中心颜色")]
        [Category("HslControls")]
        [DefaultValue(typeof(Color), "DodgerBlue")]
        public Color ActiveLineCenterColor
        {
            get => this.colorPipeLineCenter;
            set
            {
                this.colorPipeLineCenter = value;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置管道的宽度,默认为30</summary>
        [Browsable(true)]
        [Description("获取或设置管道的宽度,默认为30")]
        [Category("HslControls")]
        [DefaultValue(30)]
        public int PipeWidth
        {
            get => this.pipeWidth;
            set
            {
                this.pipeWidth = value;
                this.Invalidate();
            }
        }

        /// <summary>获取或设置蚂蚁线的长度信息</summary>
        [Browsable(true)]
        [Description("获取或设置蚂蚁线的长度信息")]
        [Category("HslControls")]
        [DefaultValue(5f)]
        public float AntLength
        {
            get => this.antLength;
            set
            {
                this.antLength = value;
                this.Invalidate();
            }
        }

        /// <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(HslPipeLineThree);
            this.Size = new Size(135, 83);
            this.ResumeLayout(false);
        }
    }
}