using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;

namespace HslCommunication.BasicFramework
{
    /*******************************************************************************
     * 
     *    Create Date:2017-05-03 16:56:39
     *    应该包含常用的绘图方法,资源,比如绘制直方图,居中的文本等
     * 
     * 
     ********************************************************************************/


    /// <summary>
    /// 图形的方向
    /// </summary>
    public enum GraphDirection
    {
        /// <summary>
        /// 向上
        /// </summary>
        Upward=1,
        /// <summary>
        /// 向下
        /// </summary>
        Downward=2,
        /// <summary>
        /// 向左
        /// </summary>
        Ledtward=3,
        /// <summary>
        /// 向右
        /// </summary>
        Rightward=4,

    }





    /// <summary>
    /// 包含整型和字符串描述的数据类型
    /// </summary>
    public struct Paintdata
    {
        /// <summary>
        /// 数量
        /// </summary>
        public int Count { get; set; }
        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; set; }
    }





    /// <summary>
    /// 图形的呈现方式
    /// </summary>
    public enum GraphicRender
    {
        /// <summary>
        /// 直方图
        /// </summary>
        Histogram = 1,
        /// <summary>
        /// 饼图
        /// </summary>
        Piechart,
        /// <summary>
        /// 折线图
        /// </summary>
        Linegraph,
    }
    /// <summary>
    /// 静态类,包含了几个常用的画图方法,获取字符串,绘制小三角等
    /// </summary>
    public static class SoftPainting
    {

        /********************************************************************************************************
         * 
         *     以下都是辅助绘图的静态方法
         * 
         * 
         * 
         * 
         ***********************************************************************************************************/

        /// <summary>
        /// 获取一个直方图
        /// </summary>
        /// <param name="array">数据数组</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="degree">刻度划分等级</param>
        /// <param name="lineColor">线条颜色</param>
        /// <returns></returns>
        public static Bitmap GetGraphicFromArray(int[] array, int width, int height, int degree, Color lineColor)
        {
            if (width < 10 && height < 10) throw new ArgumentException("长宽不能小于等于10");
            int Max = array.Max();
            int Min = 0;
            int Count = array.Length;

            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Far;
            Pen dash = new Pen(Color.LightGray, 1f);
            dash.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
            dash.DashPattern = new float[] { 5, 5 };

            Font font_8 = new Font("宋体", 9f);
            Bitmap bitmap = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(bitmap);
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.Clear(Color.White);
            //计算边框长度及图像边距
            int left = 60, right = 8, up = 8, down = 8;
            int paint_width = width - left - right;
            int paint_heigh = height - up - down;

            Rectangle rect = new Rectangle(left - 1, up - 1, paint_width + 1, paint_heigh + 1);
            //g.FillRectangle(Brushes.WhiteSmoke, rect);
            g.DrawLine(Pens.Gray, left - 1, up, left + paint_width + 1, up);
            g.DrawLine(Pens.Gray, left - 1, up + paint_heigh + 1, left + paint_width + 1, up + paint_heigh + 1);
            g.DrawLine(Pens.Gray, left - 1, up - 1, left - 1, up + paint_heigh + 1);

            //画刻度
            //for (int i = 0; i <= degree; i++)
            //{
            //    int value = (Max - Min) * i / degree + Min;
            //    int location = (int)ComputePaintLocationY(Max, Min, paint_heigh, value) + up + 1;
            //    g.DrawLine(Pens.DimGray, left - 1, location, left - 4, location);
            //    if (i != 0 && i < degree)
            //    {
            //        g.DrawLine(dash, left, location, width - right, location);
            //    }
            //    g.DrawString(value.ToString(), font_8, Brushes.DimGray, new Rectangle(-5, location - 4, left, 10), sf);
            //}

            PaintCoordinateDivide(g, Pens.DimGray, dash, font_8, Brushes.DimGray, sf, degree, Max, Min, width, height, left, right, up, down);


            PointF[] alldata = new PointF[array.Length];
            for (int i = 0; i < array.Length; i++)
            {
                alldata[i].X = paint_width * 1.0f / (array.Length - 1) * i + left;
                alldata[i].Y = ComputePaintLocationY(Max, Min, paint_heigh, array[i]) + up + 1;
            }

            Pen pen = new Pen(lineColor);
            g.DrawLines(pen, alldata);

            pen.Dispose();
            dash.Dispose();
            font_8.Dispose();
            sf.Dispose();
            g.Dispose();
            return bitmap;
        }







        /// <summary>
        /// 计算绘图时的相对偏移值
        /// </summary>
        /// <param name="max">0-100分的最大值,就是指准备绘制的最大值</param>
        /// <param name="min">0-100分的最小值,就是指准备绘制的最小值</param>
        /// <param name="height">实际绘图区域的高度</param>
        /// <param name="value">需要绘制数据的当前值</param>
        /// <returns>相对于0的位置,还需要增加上面的偏值</returns>
        public static float ComputePaintLocationY(int max, int min, int height, int value)
        {
            return height - (value - min) * 1.0f / (max - min) * height;
        }

        /// <summary>
        /// 计算绘图时的相对偏移值
        /// </summary>
        /// <param name="max">0-100分的最大值,就是指准备绘制的最大值</param>
        /// <param name="min">0-100分的最小值,就是指准备绘制的最小值</param>
        /// <param name="height">实际绘图区域的高度</param>
        /// <param name="value">需要绘制数据的当前值</param>
        /// <returns>相对于0的位置,还需要增加上面的偏值</returns>
        public static float ComputePaintLocationY( float max, float min, int height, float value )
        {
            return height - (value - min) / (max - min) * height;
        }


        /// <summary>
        /// 绘制坐标系中的刻度线
        /// </summary>
        /// <param name="g"></param>
        /// <param name="penLine"></param>
        /// <param name="penDash"></param>
        /// <param name="font"></param>
        /// <param name="brush"></param>
        /// <param name="sf"></param>
        /// <param name="degree"></param>
        /// <param name="max"></param>
        /// <param name="min"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <param name="up"></param>
        /// <param name="down"></param>
        public static void PaintCoordinateDivide(
            Graphics g,       
            Pen penLine,
            Pen penDash,
            Font font,
            Brush brush,
            StringFormat sf,
            int degree,
            int max,
            int min,
            int width,
            int height,
            int left = 60,
            int right = 8, 
            int up = 8,
            int down = 8
            )
        {
            for (int i = 0; i <= degree; i++)
            {
                int value = (max - min) * i / degree + min;
                int location = (int)ComputePaintLocationY(max, min, (height - up - down), value) + up + 1;
                g.DrawLine(penLine, left - 1, location, left - 4, location);
                if (i != 0)
                {
                    g.DrawLine(penDash, left, location, width - right, location);
                }
                g.DrawString(value.ToString(), font, brush, new Rectangle(-5, location - font.Height / 2, left, font.Height), sf);
            }
        }

        /// <summary>
        /// 根据指定的方向绘制一个箭头
        /// </summary>
        /// <param name="g"></param>
        /// <param name="brush"></param>
        /// <param name="point"></param>
        /// <param name="size"></param>
        /// <param name="direction"></param>
        public static void PaintTriangle(Graphics g, Brush brush, Point point, int size, GraphDirection direction)
        {
            Point[] points = new Point[4];
            if (direction == GraphDirection.Ledtward)
            {
                points[0] = new Point(point.X, point.Y - size);
                points[1] = new Point(point.X, point.Y + size);
                points[2] = new Point(point.X - 2 * size, point.Y);
            }
            else if (direction == GraphDirection.Rightward)
            {
                points[0] = new Point(point.X, point.Y - size);
                points[1] = new Point(point.X, point.Y + size);
                points[2] = new Point(point.X + 2 * size, point.Y);
            }
            else if (direction == GraphDirection.Upward)
            {
                points[0] = new Point(point.X - size, point.Y);
                points[1] = new Point(point.X + size, point.Y);
                points[2] = new Point(point.X, point.Y - 2 * size);
            }
            else
            {
                points[0] = new Point(point.X - size, point.Y);
                points[1] = new Point(point.X + size, point.Y);
                points[2] = new Point(point.X, point.Y + 2 * size);
            }

            points[3] = points[0];
            g.FillPolygon(brush, points);
        }








        /********************************************************************************************************
         * 
         *     以下都是生成图形类的静态方法
         * 
         * 
         * 
         * 
         ***********************************************************************************************************/



        /// <summary>
        /// 根据数据生成一个可视化的图形
        /// </summary>
        /// <param name="array">数据集合</param>
        /// <param name="width">需要绘制图形的宽度</param>
        /// <param name="height">需要绘制图形的高度</param>
        /// <param name="graphic">指定绘制成什么样子的图形</param>
        /// <returns>返回一个bitmap对象</returns>
        public static Bitmap GetGraphicFromArray(Paintdata[] array, int width, int height, GraphicRender graphic)
        {
            if (width < 10 && height < 10) throw new ArgumentException("长宽不能小于等于10");
            array.Max(m => m.Count);
            Action<Paintdata[], GraphicRender, Graphics> paintAction =
                delegate (Paintdata[] array1, GraphicRender graphic1, Graphics g)
                {

                };
            return null;
        }

        
    }
}