using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace ryControls
{
    /// <summary>
    /// 图标列表控件
    /// </summary>
    public class IconViewEx : ListView
    {
        /// <summary>
        /// 图标列表控件
        /// </summary>
        public IconViewEx() :
            base()
        {
            // 开启双缓冲
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
            this.OwnerDraw = true;//用于启用重绘
            this.View = View.Tile;
            this.TileSize = new Size(100,100);
            this.MultiSelect = false;
        }
        private int iconsize = 64;
        /// <summary>
        /// 图标大小
        /// </summary>
        [Description("图标大小")]
        public int IconSize {
            get { return iconsize; }
            set
            {
                if(value>14 && value<=512)
                {
                    iconsize = value;
                }
                else { iconsize = 64; }
            }
        }
        private int textheight = 20;
        /// <summary>
        /// 文本显示高度(从底部算起)
        /// </summary>
        [Description("文本显示高度(从底部算起)")]
        public int TextHeight
        {
            get { return textheight; }
            set
            {
                if (value > 5 && value <= 100)
                {
                    textheight = value;
                }
                else { textheight = 20; }
            }
        }
        /// <summary>
        /// 默认图标
        /// </summary>
        [Description("默认图标")]
        public Image Icon { get; set; }

        /// <summary>
        /// 是否显示图标
        /// </summary>
        [Description("是否显示图标")]
        public bool IsDrawIcon { get; set; } = true;

        /// <summary>
        /// 是否显示网格线
        /// </summary>
        [Description("是否显示网格线")]
        public bool IsDrawGridLines { get; set; }
        /// <summary>
        /// 角标图标合集
        /// </summary>
        public List<Image> BadgeListImage { get; set; } = new List<Image>();
        /// <summary>
        /// 画项
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDrawItem(DrawListViewItemEventArgs e)
        {
            Rectangle r = e.Bounds;
            Graphics g = e.Graphics;

            DrawSelectedBackground(e, g, r);

            int paddingHeight = 0;
            if (IsDrawIcon)
            {
                var soft = (Interface.IItemInfo)e.Item.Tag;
                if (soft == null || soft.Image == null)
                { paddingHeight = this.DrawIcon(g, r, this.Icon, e.Item.BackColor,-1).Height; }
                else
                {
                    paddingHeight = this.DrawIcon(g, r, soft.Image, e.Item.BackColor, soft.BadgeImageIndex).Height;
                }
            }

            //if (IsDrawGridLines)
            //{
            //    using (Pen pen = new Pen(Color.Gray))
            //    {
            //        g.DrawRectangle(pen, r.X, r.Y, r.Width, r.Height + 1);//高度加1使横向线条重叠
            //    }
            //}

            if (!string.IsNullOrEmpty(e.Item.Text))
            {
                this.DrawText(e, g, r, paddingHeight);
            }
        }
        private Color _SelectedStartBackColor = Color.FromArgb(255, 251, 237);
        /// <summary>
        /// 选择项的背景开始颜色
        /// </summary>
        [Description("选择项的背景开始颜色")]
        public Color SelectedStartBackColor
        {
            get
            {
                return _SelectedStartBackColor;
            }
            set
            {
                _SelectedStartBackColor = value;
                this.Refresh();
            }
        }
        private Color _SelectedEndBackColor = Color.FromArgb(255, 236, 181);
        /// <summary>
        /// 选择项的背景结束颜色
        /// </summary>
        [Description("选择项的背景结束颜色")]
        public Color SelectedEndBackColor
        {
            get
            {
                return _SelectedEndBackColor;
            }
            set
            {
                _SelectedEndBackColor = value;
                this.Refresh();
            }
        }
        private Color _SelectedBorderColor = Color.FromArgb(229, 195, 101);
        /// <summary>
        /// 选择项的边框颜色
        /// </summary>
        [Description("选择项的边框颜色")]
        public Color SelectedBorderColor
        {
            get
            {
                return _SelectedBorderColor;
            }
            set
            {
                _SelectedBorderColor = value;
                this.Refresh();
            }
        }
        private Color _SelectedForeColor = Color.Black;
        /// <summary>
        /// 选择项的字体颜色
        /// </summary>
        [Description("选择项的字体颜色")]
        public Color SelectedForeColor
        {
            get
            {
                return _SelectedForeColor;
            }
            set
            {
                _SelectedForeColor = value;
                this.Refresh();
            }
        }
        /// <summary>
        /// 重绘选中时背景
        /// </summary>
        private void DrawSelectedBackground(DrawListViewItemEventArgs e, Graphics g, Rectangle r)
        {
            if (e.Item.Selected)
            {
                //渐变画刷
                LinearGradientBrush brush = new LinearGradientBrush(e.Bounds, _SelectedStartBackColor,
                                                 _SelectedEndBackColor, LinearGradientMode.Vertical);
                //填充区域
                //Rectangle borderRect = new Rectangle(r, e.Bounds.Y, e.Bounds.Width - 5, e.Bounds.Height - 2);
                e.Graphics.FillRectangle(brush, r);
                brush.Dispose();
                ////画边框
                Pen pen = new Pen(_SelectedBorderColor);
                Rectangle borderRect = r;
                borderRect.Width--;
                borderRect.Height--;
                e.Graphics.DrawRectangle(pen, borderRect);
                pen.Dispose();
                //using (SolidBrush brush = new SolidBrush(_SelectedBackColor))
                //{
                //    g.FillRectangle(brush, r);
                //}
            }
        }

        /// <summary>
        /// 重绘图标
        /// </summary>
        /// <param name="g"></param>
        /// <param name="r">区域大小</param>
        /// <param name="image"></param>
        /// <param name="backColor"></param>
        /// <param name="BadgeImageIndex"></param>
        /// <returns></returns>
        private Size DrawIcon(Graphics g, Rectangle r, Image image, Color backColor,int BadgeImageIndex)
        {
            var x = r.X + ((r.Width - iconsize) / 2);
            var y = r.Y + ((r.Height - textheight - iconsize) / 2);
            Rectangle imageBounds = new Rectangle(new Point(x,y), new Size(iconsize, iconsize));           
            if (image.Width > image.Height)
            {
                imageBounds.Height =(int)((image.Height/(double)image.Width)* imageBounds.Width);
                y += ((iconsize - imageBounds.Height) / 2);
            }
            else
            {
                x +=  ((iconsize - imageBounds.Width) / 2);
                imageBounds.Width = (int)((image.Width / (double)image.Height) * imageBounds.Height);
            }
            imageBounds.X = x;
            imageBounds.Y = y;
            //imageBounds.X = r.X + (r.Width - imageBounds.Width) / 2;
            //使图标不会紧贴着每一列的左上角
            //imageBounds.X += 1;
            //imageBounds.Y += 1;
            //如果有角标,则显示角标
            g.DrawImage(image, imageBounds);
            if (BadgeImageIndex >= 0 && BadgeImageIndex < BadgeListImage.Count)
            {
                var badge = BadgeListImage[BadgeImageIndex];
                if (badge != null)
                {
                    var size = imageBounds.Width / 5;
                    var badge_rect = new Rectangle(imageBounds.Left + size * 4, imageBounds.Top, size, size);
                    g.DrawImage(badge, badge_rect);
                }
            }
            return imageBounds.Size;
        }

        /// <summary>
        /// 重绘文本
        /// </summary>
        private void DrawText(DrawListViewItemEventArgs e, Graphics g, Rectangle r, int paddingHeight)
        {
            TextFormatFlags flags = GetFormatFlags(HorizontalAlignment.Center);
            var r1 = new Rectangle(r.Location, r.Size)
            {
                Y = r.Y + r.Height- textheight,//重绘图标时，文本右移
                Height = textheight
            };
            TextRenderer.DrawText(
                g,
                e.Item.Text,
                e.Item.Font,
                r1,
                e.Item.Selected ? SelectedForeColor : e.Item.ForeColor,
                flags);
        }

        /// <summary>
        /// 获取文本对齐
        /// </summary>
        private TextFormatFlags GetFormatFlags(
            HorizontalAlignment align)
        {
            TextFormatFlags flags =
                    TextFormatFlags.EndEllipsis |
                    TextFormatFlags.VerticalCenter;

            switch (align)
            {
                case HorizontalAlignment.Center:
                    flags |= TextFormatFlags.HorizontalCenter;
                    break;
                case HorizontalAlignment.Right:
                    flags |= TextFormatFlags.Right;
                    break;
                case HorizontalAlignment.Left:
                    flags |= TextFormatFlags.Left;
                    break;
            }

            return flags;
        }
        const int WM_HSCROLL = 0x0114;
        const int WM_VSCROLL = 0x0115;
        /// <summary>
        /// 水平滚动条滚动事件
        /// </summary>
        [Description("水平滚动条滚动事件")]
        public event EventHandler HScroll;
        /// <summary>
        /// 垂直滚动条滚动事件
        /// </summary>
        [Description("垂直滚动条滚动事件")]
        public event EventHandler VScroll;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_HSCROLL)
            {
                HScroll?.Invoke(this, new EventArgs());
            }
            else if (m.Msg == WM_VSCROLL)
            {
                VScroll?.Invoke(this, new EventArgs());
            }
            base.WndProc(ref m);
        }
    }
}