using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Data;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms.DataVisualization.Charting;


namespace FLY.ControlLibrary
{
    /// <summary>
    /// GraphScan.xaml 的交互逻辑
    /// </summary>
    public partial class GraphScan_coslight : GraphScan
    {


        public GraphScan_coslight():base()
        {
            this.chart1.SizeChanged += new EventHandler(chart1_SizeChanged);
            this.PropertyChanged += new PropertyChangedEventHandler(GraphScan_coslight_PropertyChanged);
        }

        void GraphScan_coslight_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsReversed")
            {
                chart1.ChartAreas[0].AxisX.IsReversed = IsReversed;
                if (!IsReversed)
                    chart1.ChartAreas[0].Position.X = 0F;
                else
                    chart1.ChartAreas[0].Position.X = 100F - chart1.ChartAreas[0].Position.Width;
            }
        }

        /// <summary>
        /// 解决右边坐标显示问题
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void chart1_SizeChanged(object sender, EventArgs e)
        {

            ChartArea area = chart1.ChartAreas[0];
            Graphics g = chart1.CreateGraphics();
            SizeF size = g.MeasureString("目标值", area.AxisY.LabelStyle.Font);//获取字符串尺寸
            float pw = 100 * (chart1.Width - size.Width - 10) / chart1.Width;
            chart1.ChartAreas[0].Position.Width = (int)pw;

            chart1.ChartAreas[0].Position.Height = 100F;
            
            chart1.ChartAreas[0].Position.Y = 0F;

            if (!IsReversed)
                chart1.ChartAreas[0].Position.X = 0F;
            else 
                chart1.ChartAreas[0].Position.X = 100F - chart1.ChartAreas[0].Position.Width;
            
            g.Dispose();
        }


        /// <summary>
        /// 获取实际应用的目标值，公差
        /// </summary>
        /// <param name="target"></param>
        /// <param name="alarm"></param>
        /// <param name="yrange"></param>
        /// <param name="ctrlline"></param>
        /// <param name="ispercent"></param>
        void GetActualTargetAlarm(
            out double target,
            out double alarm,
            out double yrange,
            out double ctrlline,
            out bool ispercent)
        {
            double multi = Multi;
            if (IsAutoTarget)
                target = AutoTarget / multi;//AutoTarget 计算得到的平均值
            else
                target = Target / multi;

            ispercent = IsPercent;
            if ((ispercent) && (Target <= 0) || (Alarm < 0) || (target <= 0))
                ispercent = false;

            if (ispercent)
            {
                alarm = target * Alarm / Target;
            }
            else
            {
                alarm = Alarm / multi;
            }
            yrange = alarm * YRangePercent;

            if ((alarm < 0.1) || (yrange < 0.3))
            {
                alarm = 0.1;
                yrange = 0.3;
            }

            ctrlline = CtrlLine / multi;
        }



        /// <summary>
        /// 画虚线 与 右坐标
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected override void Chart1_PrePaint(object sender, System.Windows.Forms.DataVisualization.Charting.ChartPaintEventArgs e)
        {
            if (e.ChartElement is ChartArea)
            {

                ChartArea area = (ChartArea)e.ChartElement;
                if (Double.IsNaN(area.AxisY.Minimum))
                    return;



                double alarm;
                double yrange;
                double target;
                double ctrlline;
                bool ispercent;
                GetActualTargetAlarm(out target, out alarm, out yrange, out ctrlline, out ispercent);

                //画目标值
                System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Color.Green, 2);
                DrawYGridTick(e.ChartGraphics, pen, target);
                //画规格线
                if (alarm < yrange)
                {
                    pen.Color = System.Drawing.Color.Red;
                    DrawYGridTick(e.ChartGraphics, pen, target + alarm);
                    DrawYGridTick(e.ChartGraphics, pen, target - alarm);
                }
                //画控制线
                if (HasCtrlLine)
                {
                    if (ctrlline < yrange)
                    {
                        pen.Color = System.Drawing.Color.Orange;
                        pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
                        pen.DashPattern = new float[] { 5, 5 };
                        DrawYGridTick(e.ChartGraphics, pen, target + ctrlline);

                        pen.Color = System.Drawing.Color.Blue;
                        DrawYGridTick(e.ChartGraphics, pen, target - ctrlline);
                    }
                }

                //写字
                //if (y > area.AxisY.Maximum || y < area.AxisY.Minimum)
                //    return;

                ChartGraphics cg = e.ChartGraphics;
                Graphics graph = cg.Graphics;
                RectangleF rectangele_target = new RectangleF();
                RectangleF rectangele_alarm_min = new RectangleF();
                RectangleF rectangele_alarm_max = new RectangleF();
                RectangleF rectangele_ctrlline_min = new RectangleF();
                RectangleF rectangele_ctrlline_max = new RectangleF();

                rectangele_target.Size = graph.MeasureString("目标值", area.AxisY.LabelStyle.Font);//获取字符串尺寸

                double XMax = cg.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Maximum);
                cg.GetAbsolutePoint(
                    new System.Drawing.PointF()
                    {
                        X = (float)(XMax),
                        Y = 0
                    });



                // Convert relative coordinates to absolute coordinates.
                rectangele_target.Location = cg.GetAbsolutePoint(new System.Drawing.PointF() { X = (float)(XMax), Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target) });

                if (!IsReversed)
                    rectangele_target.X += 2;
                else 
                    rectangele_target.X -= (rectangele_target.Width + 2);

                rectangele_target.Y -= rectangele_target.Height / 2;//移到中间


                graph.DrawString(
                    "目标值",
                    area.AxisY.LabelStyle.Font,
                    new System.Drawing.SolidBrush(System.Drawing.Color.Green), rectangele_target);


                //画控制线
                if (HasCtrlLine)
                {
                    if ((ctrlline < yrange) && (ctrlline < alarm))
                    {

                        rectangele_ctrlline_min.Size = graph.MeasureString("控制线", area.AxisY.LabelStyle.Font);//获取字符串尺寸

                        // Convert relative coordinates to absolute coordinates.
                        rectangele_ctrlline_min.Location =
                            cg.GetAbsolutePoint(
                            new System.Drawing.PointF()
                            {
                                X = (float)(XMax),
                                Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target - ctrlline)
                            });

                        if (!IsReversed)
                            rectangele_ctrlline_min.X += 2;
                        else
                            rectangele_ctrlline_min.X -= (rectangele_ctrlline_min.Width + 2);
                        

                        rectangele_ctrlline_min.Y -= rectangele_ctrlline_min.Height / 2;//移到中间

                        if (rectangele_ctrlline_min.Top < rectangele_target.Bottom)
                        {
                            rectangele_ctrlline_min.Y = rectangele_target.Bottom;
                        }

                        graph.DrawString(
                            "控制线",
                            area.AxisY.LabelStyle.Font,
                            new System.Drawing.SolidBrush(System.Drawing.Color.Blue), rectangele_ctrlline_min);



                        rectangele_ctrlline_max.Size = graph.MeasureString("控制线", area.AxisY.LabelStyle.Font);//获取字符串尺寸

                        // Convert relative coordinates to absolute coordinates.
                        rectangele_ctrlline_max.Location =
                            cg.GetAbsolutePoint(
                            new System.Drawing.PointF()
                            {
                                X = (float)(XMax),
                                Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target + ctrlline)
                            });


                        if (!IsReversed)
                            rectangele_ctrlline_max.X += 2;
                        else
                            rectangele_ctrlline_max.X -= (rectangele_ctrlline_max.Width + 2);

                        rectangele_ctrlline_max.Y -= rectangele_ctrlline_max.Height / 2;//移到中间

                        if (rectangele_ctrlline_max.Bottom > rectangele_target.Top)
                        {
                            rectangele_ctrlline_max.Y = rectangele_target.Top - rectangele_ctrlline_max.Height;
                        }

                        graph.DrawString(
                            "控制线",
                            area.AxisY.LabelStyle.Font,
                            new System.Drawing.SolidBrush(System.Drawing.Color.Orange), rectangele_ctrlline_max);
                    }
                }


                //规格线
                if (alarm < yrange)
                {
                    rectangele_alarm_min.Size = graph.MeasureString("规格线", area.AxisY.LabelStyle.Font);//获取字符串尺寸

                    // Convert relative coordinates to absolute coordinates.
                    rectangele_alarm_min.Location =
                        cg.GetAbsolutePoint(
                        new System.Drawing.PointF()
                        {
                            X = (float)(XMax),
                            Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target - alarm)
                        });


                    if (!IsReversed)
                        rectangele_alarm_min.X += 2;
                    else
                        rectangele_alarm_min.X -= (rectangele_alarm_min.Width + 2);

                    rectangele_alarm_min.Y -= rectangele_alarm_min.Height / 2;//移到中间

                    if (HasCtrlLine && (ctrlline < alarm))
                    {
                        if (rectangele_alarm_min.Top < rectangele_ctrlline_min.Bottom)
                        {
                            rectangele_alarm_min.Y = rectangele_ctrlline_min.Bottom;
                        }
                    }
                    else
                    {
                        if (rectangele_alarm_min.Top < rectangele_target.Bottom)
                        {
                            rectangele_alarm_min.Y = rectangele_target.Bottom;
                        }
                    }

                    graph.DrawString(
                        "规格线",
                        area.AxisY.LabelStyle.Font,
                        new System.Drawing.SolidBrush(System.Drawing.Color.Red), rectangele_alarm_min);


                    rectangele_alarm_max.Size = graph.MeasureString("规格线", area.AxisY.LabelStyle.Font);//获取字符串尺寸

                    // Convert relative coordinates to absolute coordinates.
                    rectangele_alarm_max.Location =
                        cg.GetAbsolutePoint(
                        new System.Drawing.PointF()
                        {
                            X = (float)(XMax),
                            Y = (float)cg.GetPositionFromAxis(area.Name, AxisName.Y, target + alarm)
                        });

                    if (!IsReversed)
                        rectangele_alarm_max.X += 2;
                    else
                        rectangele_alarm_max.X -= (rectangele_alarm_max.Width + 2);

                    rectangele_alarm_max.Y -= rectangele_alarm_max.Height / 2;//移到中间

                    if (HasCtrlLine && (ctrlline < alarm))
                    {
                        if (rectangele_alarm_max.Bottom > rectangele_ctrlline_max.Top)
                        {
                            rectangele_alarm_max.Y = rectangele_ctrlline_max.Top - rectangele_alarm_max.Height;
                        }
                    }
                    else
                    {
                        if (rectangele_alarm_max.Bottom > rectangele_target.Top)
                        {
                            rectangele_alarm_max.Y = rectangele_target.Top - rectangele_alarm_max.Height;
                        }
                    }
                    graph.DrawString(
                        "规格线",
                        area.AxisY.LabelStyle.Font,
                        new System.Drawing.SolidBrush(System.Drawing.Color.Red), rectangele_alarm_max);

                }
            }
        }

        void DrawYGridTick(ChartGraphics cg, System.Drawing.Pen pen, double y)
        {
            ChartArea area = chart1.ChartAreas[0];

            if (y > area.AxisY.Maximum || y < area.AxisY.Minimum)
                return;

            // Take Graphics object from chart
            Graphics graph = cg.Graphics;

            // Convert X and Y values to screen position
            double py = cg.GetPositionFromAxis(area.Name, AxisName.Y, y);

            double XMin = cg.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Minimum);
            double XMax = cg.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Maximum);

            System.Drawing.PointF[] points = new System.Drawing.PointF[2];
            points[0].X = (float)XMin;
            points[1].X = (float)XMax;
            points[0].Y = points[1].Y = (float)py;

            // Convert relative coordinates to absolute coordinates.
            points[0] = cg.GetAbsolutePoint(points[0]);
            points[1] = cg.GetAbsolutePoint(points[1]);

            graph.DrawLine(pen, points[0], points[1]);

        }

        void DrawYLabel(ChartGraphics cg, System.Drawing.Brush brush, Font font, double y, string msg)
        {
            ChartArea area = chart1.ChartAreas[0];

            if (y > area.AxisY.Maximum || y < area.AxisY.Minimum)
                return;

            // Take Graphics object from chart
            Graphics graph = cg.Graphics;

            // Convert X and Y values to screen position
            double py = cg.GetPositionFromAxis(area.Name, AxisName.Y, y);

            double XMax = cg.GetPositionFromAxis(area.Name, AxisName.X, area.AxisX.Maximum);

            System.Drawing.PointF point = new System.Drawing.PointF();
            point.X = (float)XMax;
            point.Y = (float)py;

            // Convert relative coordinates to absolute coordinates.
            point = cg.GetAbsolutePoint(point);


            graph.DrawString(msg, font, brush, point);

        }

        /// <summary>
        /// 与 Multi,Target,YRange,Alarm 相关
        /// </summary>
        public override void UpdateAxisY()
        {

            double alarm;
            double yrange;
            double target;
            double ctrlline;
            bool ispercent;
            GetActualTargetAlarm(out target, out alarm, out yrange, out ctrlline, out ispercent);


            Axis axisY = chart1.ChartAreas["Default"].AxisY;

            axisY.Crossing = target;

            // Set manual minimum and maximum values.
            axisY.Minimum = target - yrange;
            axisY.Maximum = target + yrange;

            axisY.CustomLabels.Clear();
            //中间目标值,肯定不以%显示
            SetCustomLabel(axisY, target, GridTickTypes.All, System.Drawing.Color.Green, false, null);

            //上下限
            SetCustomLabel(axisY, target + alarm, GridTickTypes.All, System.Drawing.Color.Red, ispercent, null);
            SetCustomLabel(axisY, target - alarm, GridTickTypes.All, System.Drawing.Color.Red, ispercent, null);

            //显示范围数值
            SetCustomLabel(axisY, axisY.Minimum, GridTickTypes.All, System.Drawing.Color.DarkViolet, ispercent, null);
            SetCustomLabel(axisY, axisY.Maximum, GridTickTypes.All, System.Drawing.Color.DarkViolet, ispercent, null);

            //显示范围数值
            if (yrange != 2 * alarm)
            {
                SetCustomLabel(axisY, target + alarm * 2, GridTickTypes.TickMark, System.Drawing.Color.Black, ispercent, null);
                SetCustomLabel(axisY, target - alarm * 2, GridTickTypes.TickMark, System.Drawing.Color.Black, ispercent, null);
            }

            //显示范围太小，多加纵坐标
            if (yrange <= alarm)
            {
                SetCustomLabel(axisY, target - yrange / 2, GridTickTypes.All, System.Drawing.Color.Black, ispercent, null);
                SetCustomLabel(axisY, target + yrange / 2, GridTickTypes.All, System.Drawing.Color.Black, ispercent, null);
            }



        }
        protected override void UpdateOnePoint(int index)
        {
            double multi = Multi;
            int emptyvalue = EmptyValue;
            DataPoint point;
            if (index >= chart1.Series["Series 1"].Points.Count)
            {
                chart1.Series["Series 1"].Points.AddXY(
                FirstBoltNo + index,
                (double)DataSource[index] / multi);
                point = chart1.Series["Series 1"].Points[index];
            }
            else
            {

                point = chart1.Series["Series 1"].Points[index];

                point.YValues[0] = DataSource[index] / multi;
                point.XValue = FirstBoltNo + index;
            }
            //设定空数据

            if (DataSource[index] == emptyvalue)
            {
                point.IsEmpty = true;
            }
            else
            {
                point.IsEmpty = false;
            }

            System.Drawing.Color c;

            double alarm;
            double yrange;
            double target;
            double ctrlline;
            bool ispercent;
            GetActualTargetAlarm(out target, out alarm, out yrange, out ctrlline, out ispercent);

            double data = DataSource[index] / multi;


            if (data > (target + yrange))
            {
                c = System.Drawing.Color.Violet;
            }
            else if (data > (target + alarm))
            {
                c = System.Drawing.Color.Red;
            }
            else if (data >= (target - alarm))
            {
                if (HasCtrlLine)
                {
                    if (data > (target + ctrlline))
                    {
                        c = System.Drawing.Color.Orange;
                    }
                    else if (data >= (target - ctrlline))
                    {
                        c = System.Drawing.Color.Green;
                    }
                    else
                    {
                        c = System.Drawing.Color.FromArgb(0x00,0x8B,0xE5);
                    }
                }
                else
                {
                    c = System.Drawing.Color.Green;
                }
            }
            else if (data >= (target - yrange))
            {
                c = System.Drawing.Color.Red;
            }
            else
            {
                c = System.Drawing.Color.Violet;
            }


            if (ChartType == SeriesChartType.Line)
            {
                point.MarkerColor = c;
                point.BorderColor = chart1.Series["Series 1"].BorderColor;
                point.Color = chart1.Series["Series 1"].Color;
            }
            else
            {
                point.MarkerColor = c;
                point.BorderColor = c;
                point.Color = c;
            }
        }

    }

}
