using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
namespace FurnaceUI.Controls
{
   /// 
   /// 整个组件的代码辅助工具,提供了一个基础的类库方法
   /// 
    public class Helper
    {
        /// 
        /// 从一个矩形的图形中获取菱形的坐标数组
        /// 
        /// 矩形
        /// 数组结果
        public static Point[] GetRhombusFromRectangle(Rectangle rect)
        {
            return new Point[]
            {
                new Point(rect.X, rect.Y + rect.Height / 2),
                new Point(rect.X + rect.Width / 2, rect.Y + rect.Height - 1),
                new Point(rect.X + rect.Width - 1, rect.Y + rect.Height / 2),
                new Point(rect.X + rect.Width / 2, rect.Y),
                new Point(rect.X, rect.Y + rect.Height / 2),
            };
        }
        /// 
        /// 计算绘图时的相对偏移值
        /// 
        /// 0-100分的最大值,就是指准备绘制的最大值
        /// 0-100分的最小值,就是指准备绘制的最小值
        /// 实际绘图区域的高度
        /// 需要绘制数据的当前值
        /// 相对于0的位置,还需要增加上面的偏值
        public static float ComputePaintLocationY(int max, int min, int height, int value)
        {
            if ((max - min) == 0f)
            {
                return height;
            }
            else
            {
                return height - (value - min) * 1.0f / (max - min) * height;
            }
        }
        /// 
        /// 计算绘图时的相对偏移值
        /// 
        /// 0-100分的最大值,就是指准备绘制的最大值
        /// 0-100分的最小值,就是指准备绘制的最小值
        /// 实际绘图区域的高度
        /// 需要绘制数据的当前值
        /// 相对于0的位置,还需要增加上面的偏值
        public static float ComputePaintLocationY(float max, float min, float height, float value)
        {
            if ((max - min) == 0f)
            {
                return height;
            }
            else
            {
                return height - (value - min) / (max - min) * height;
            }
        }
        /// 
        /// 绘制坐标系中的刻度线
        /// 
        /// 绘图对象
        /// 画坐标轴的画笔
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        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);
            }
        }
        /// 
        /// 根据指定的方向绘制一个箭头
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void PaintTriangle(Graphics g, Brush brush, Point point, int size, GraphDirection direction)
        {
            Point[] points = new Point[4];
            if (direction == GraphDirection.Leftward)
            {
                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);
        }
        /// 
        /// 根据指定的方向绘制一个箭头
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void PaintTriangle(Graphics g, Brush brush, PointF point, int size, GraphDirection direction)
        {
            PointF[] points = new PointF[4];
            if (direction == GraphDirection.Leftward)
            {
                points[0] = new PointF(point.X, point.Y - size);
                points[1] = new PointF(point.X, point.Y + size);
                points[2] = new PointF(point.X - 2 * size, point.Y);
            }
            else if (direction == GraphDirection.Rightward)
            {
                points[0] = new PointF(point.X, point.Y - size);
                points[1] = new PointF(point.X, point.Y + size);
                points[2] = new PointF(point.X + 2 * size, point.Y);
            }
            else if (direction == GraphDirection.Upward)
            {
                points[0] = new PointF(point.X - size, point.Y);
                points[1] = new PointF(point.X + size, point.Y);
                points[2] = new PointF(point.X, point.Y - 2 * size);
            }
            else
            {
                points[0] = new PointF(point.X - size, point.Y);
                points[1] = new PointF(point.X + size, point.Y);
                points[2] = new PointF(point.X, point.Y + 2 * size);
            }
            points[3] = points[0];
            g.FillPolygon(brush, points);
        }
        /// 
        /// 一个通用的数组新增个数方法,会自动判断越界情况,越界的情况下,会自动的截断或是填充 -> 
        /// A common array of new methods, will automatically determine the cross-border situation, in the case of cross-border, will be automatically truncated or filled
        /// 
        /// 数据类型
        /// 原数据
        /// 等待新增的数据
        /// 原数据的最大值
        public static void AddArrayData(ref T[] array, T[] data, int max)
        {
            if (data == null) return;           // 数据为空
            if (data.Length == 0) return;       // 数据长度为空
            if (array.Length == max)
            {
                Array.Copy(array, data.Length, array, 0, array.Length - data.Length);
                Array.Copy(data, 0, array, array.Length - data.Length, data.Length);
            }
            else
            {
                if ((array.Length + data.Length) > max)
                {
                    T[] tmp = new T[max];
                    for (int i = 0; i < (max - data.Length); i++)
                    {
                        tmp[i] = array[i + (array.Length - max + data.Length)];
                    }
                    for (int i = 0; i < data.Length; i++)
                    {
                        tmp[tmp.Length - data.Length + i] = data[i];
                    }
                    // 更新数据
                    array = tmp;
                }
                else
                {
                    T[] tmp = new T[array.Length + data.Length];
                    for (int i = 0; i < array.Length; i++)
                    {
                        tmp[i] = array[i];
                    }
                    for (int i = 0; i < data.Length; i++)
                    {
                        tmp[tmp.Length - data.Length + i] = data[i];
                    }
                    array = tmp;
                }
            }
        }
        /// 
        /// 尺寸转换,计算旋转后的尺寸。
        /// 
        /// 
        /// 
        /// 
        public static SizeF ConvertSize(SizeF size, float angle)
        {
            Matrix matrix = new Matrix();
            matrix.Rotate(angle);
            // 旋转矩形四个顶点  
            PointF[] pts = new PointF[4];
            pts[0].X = -size.Width / 2f;
            pts[0].Y = -size.Height / 2f;
            pts[1].X = -size.Width / 2f;
            pts[1].Y = size.Height / 2f;
            pts[2].X = size.Width / 2f;
            pts[2].Y = size.Height / 2f;
            pts[3].X = size.Width / 2f;
            pts[3].Y = -size.Height / 2f;
            matrix.TransformPoints(pts);
            // 求取四个顶点的包围盒  
            float left = float.MaxValue;
            float right = float.MinValue;
            float top = float.MaxValue;
            float bottom = float.MinValue;
            foreach (PointF pt in pts)
            {
                // 求取并集  
                if (pt.X < left)
                    left = pt.X;
                if (pt.X > right)
                    right = pt.X;
                if (pt.Y < top)
                    top = pt.Y;
                if (pt.Y > bottom)
                    bottom = pt.Y;
            }
            SizeF result = new SizeF(right - left, bottom - top);
            return result;
        }
        /// 
        /// 绘制旋转文本
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void DrawString(Graphics g, string s, Font font, Brush brush, PointF point, StringFormat format, float angle)
        {
            // Save the matrix  
            Matrix mtxSave = g.Transform;
            Matrix mtxRotate = g.Transform;
            mtxRotate.RotateAt(angle, point);
            g.Transform = mtxRotate;
            g.DrawString(s, font, brush, point, format);
            // Reset the matrix  
            g.Transform = mtxSave;
        }
        private static int GetPow(int digit)
        {
            int result = 1;
            for (int i = 0; i < digit; i++)
            {
                result *= 10;
            }
            return result;
        }
        /// 
        /// 获得数据的上限值,这个上限值是自动计算的。
        /// 
        /// 数据值
        /// 数据值
        public static int CalculateMaxSectionFrom(int[] values)
        {
            int max = values.Max();
            if (max <= 5) return 5;
            if (max <= 10) return 10;
            int digit = max.ToString().Length - 2;
            int head = int.Parse(max.ToString().Substring(0, 2));
            if (head < 12) return 12 * GetPow(digit);
            if (head < 14) return 14 * GetPow(digit);
            if (head < 16) return 16 * GetPow(digit);
            if (head < 18) return 18 * GetPow(digit);
            if (head < 20) return 20 * GetPow(digit);
            if (head < 22) return 22 * GetPow(digit);
            if (head < 24) return 24 * GetPow(digit);
            if (head < 26) return 26 * GetPow(digit);
            if (head < 28) return 28 * GetPow(digit);
            if (head < 30) return 30 * GetPow(digit);
            if (head < 40) return 40 * GetPow(digit);
            if (head < 50) return 50 * GetPow(digit);
            if (head < 60) return 60 * GetPow(digit);
            if (head < 80) return 80 * GetPow(digit);
            return 100 * GetPow(digit);
        }
        /// 
        /// 获取当前颜色更淡的颜色信息
        /// 
        /// 颜色信息
        /// 颜色
        public static Color GetColorLight(Color color)
        {
            return Color.FromArgb(color.R + (255 - color.R) * 40 / 100, color.G + (255 - color.G) * 40 / 100, color.B + (255 - color.B) * 40 / 100);
        }
        /// 
        /// 获取当前颜色更淡的颜色信息
        /// 
        /// 颜色信息
        /// 颜色
        public static Color GetColorLightFive(Color color)
        {
            return Color.FromArgb(color.R + (255 - color.R) * 50 / 100, color.G + (255 - color.G) * 50 / 100, color.B + (255 - color.B) * 50 / 100);
        }
#if NET45
        /// 
        /// 获取当前颜色更淡的颜色信息
        /// 
        /// 颜色信息
        /// 颜色
        public static System.Windows.Media.Color GetColorLight( System.Windows.Media.Color color )
        {
            return System.Windows.Media.Color.FromRgb( (byte)(color.R + (255 - color.R) * 40 / 100), (byte)(color.G + (255 - color.G) * 40 / 100), (byte)(color.B + (255 - color.B) * 40 / 100) );
        }
        /// 
        /// 获取当前颜色更淡的颜色信息
        /// 
        /// 颜色信息
        /// 颜色
        public static System.Windows.Media.Color GetColorLightFive( System.Windows.Media.Color color )
        {
            return System.Windows.Media.Color.FromRgb( (byte)(color.R + (255 - color.R) * 50 / 100), (byte)(color.G + (255 - color.G) * 50 / 100), (byte)(color.B + (255 - color.B) * 50 / 100) );
        }
#endif
        /// 
        /// 从字符串表示的点位信息里解析出真正的点位信息
        /// 
        /// 字符串的点位
        /// 原来的长度信息
        /// 原来的高度信息
        /// 实际的宽度信息
        /// 实际的高度信息
        /// x偏移量信息
        /// y偏移量信息
        /// 
        public static PointF[] GetPointsFrom(string points, float soureWidth, float sourceHeight, float width, float height, float dx = 0, float dy = 0)
        {
            string[] itemPoint = points.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            PointF[] ret = new PointF[itemPoint.Length];
            for (int i = 0; i < itemPoint.Length; i++)
            {
                int index = itemPoint[i].IndexOf(',');
                float x = Convert.ToSingle(itemPoint[i].Substring(0, index));
                float y = Convert.ToSingle(itemPoint[i].Substring(index + 1));
                ret[i] = new PointF(width * (x + dx) / soureWidth, height * (y + dy) / sourceHeight);
            }
            return ret;
        }
    }
    /// 
    /// 图形的方向
    /// 
    public enum GraphDirection
    {
        /// 
        /// 向上
        /// 
        Upward = 1,
        /// 
        /// 向下
        /// 
        Downward = 2,
        /// 
        /// 向左
        /// 
        Leftward = 3,
        /// 
        /// 向右
        /// 
        Rightward = 4,
    }
    /// 
    /// 指示控件的样子
    /// 
    public enum HslDirectionStyle
    {
        /// 
        /// 控件是横向摆放的
        /// 
        Horizontal = 1,
        /// 
        /// 控件是纵向摆放的
        /// 
        Vertical = 2
    }
    /// 
    /// 系统的主题样式,将会改变一些控件的外观
    /// 
    public enum HslThemeStyle
    {
        /// 
        /// 浅色的主题
        /// 
        Light = 1,
        /// 
        /// 深色的主题
        /// 
        Dark = 2,
    }
    /// 
    /// 某些特殊图形的表现形式
    /// 
    public enum HslRenderStyle
    {
        /// 
        /// 椭圆
        /// 
        Ellipse = 1,
        /// 
        /// 矩形
        /// 
        Rectangle = 2,
        /// 
        /// 菱形
        /// 
        Rhombus = 3
    }
    /// 
    /// 包含整型和字符串描述的数据类型
    /// 
    public struct Paintdata
    {
        /// 
        /// 数量
        /// 
        public int Count { get; set; }
        /// 
        /// 描述
        /// 
        public string Description { get; set; }
    }
    /// 
    /// 计算的基础数据 
    /// 
    public class CenterPoint
    {
        /// 
        /// 中心点的位置
        /// 
        public Point Point { get; set; }
        /// 
        /// 半径
        /// 
        public int Radius { get; set; }
        /// 
        /// 角度
        /// 
        public double Angle { get; set; }
    }
}