using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;

namespace Azyobuzi.Twirunrun
{
    public class StatusesListBox : ListBox
    {
        public StatusesListBox()
        {
            this.SelectionMode = SelectionMode.MultiExtended;
            this.DoubleBuffered = true;
            this.DrawMode = DrawMode.OwnerDrawVariable;
            this.MeasureItem +=
                (sender, e) =>
                    e.ItemHeight =
                        Math.Max(
                            Settings.Instance.IconSize,
                            (int)Settings.Instance.MainFont.GetHeight()
                        ) + 1;
            this.DrawItem += this_DrawItem;
        }

        private IList<StatusInfo> statuses = new StatusInfo[] { }.ToList();
        public IList<StatusInfo> Statuses
        {
            set
            {
                this.Invoke((MethodInvoker)(() =>
                {
                    statuses = value;
                    ResetItems();
                }));
            }
            get
            {
                return statuses;
            }
        }

        public void ResetItems()
        {
            if (statuses.Count > this.Items.Count)
            {
                this.Items.AddRange(
                    Enumerable.Range(0, statuses.Count - this.Items.Count)
                    .Select(i => string.Empty)//何でもいい
                    .ToArray()
                );
            }
            else if (statuses.Count < this.Items.Count)
            {
                this.BeginUpdate();
                Enumerable.Range(0, this.Items.Count - statuses.Count)
                    .ForEach(i => this.Items.RemoveAt(0));
                this.EndUpdate();
            }
        }

        private void this_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index < 0) return;

            var itemPoint = e.Bounds.Location;

            var post = Statuses[e.Index];

            var font = Settings.Instance.MainFont;
            var color = (e.State & DrawItemState.Selected) == DrawItemState.Selected ?
                SystemColors.HighlightText : Settings.Instance.MainFontColor;

            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

            //背景色描画
            Brush bgBrush;
            if (post.Type == StatusTypes.Retweet)
                bgBrush = new SolidBrush(Settings.Instance.RetweetedBgColor);
            else
                bgBrush = new SolidBrush(Settings.Instance.MainBgColor);

            e.Graphics.FillRectangle(bgBrush, e.Bounds);

            bgBrush.Dispose();

            e.DrawBackground();

            //ラベル描画
            if (!string.IsNullOrEmpty(post.LabelColor))
            {
                using (Brush labelBrush = new SolidBrush(post.LabelColor.ConvertToColor()))
                {
                    const int LABEL_WIDTH = 20;
                    e.Graphics.FillRectangle(labelBrush,
                        itemPoint.X + e.Bounds.Width - LABEL_WIDTH,
                        itemPoint.Y,
                        LABEL_WIDTH,
                        e.Bounds.Height
                    );
                }
            }

            //アイコン描画
            var icon = Icons.GetItem(post.ProfileImageUri);

            const int LEFT_SPACE = 2;

            var iconsize = Settings.Instance.IconSize;

            if (icon != null)
            {
                var iconpoz = new Point(itemPoint.X + LEFT_SPACE, itemPoint.Y);

                if (font.GetHeight() > iconsize)
                {
                    iconpoz.Y += (e.Bounds.Height / 2) - (iconsize / 2);
                }

                e.Graphics.DrawImage(icon, new Rectangle(iconpoz, new Size(iconsize, iconsize)));
            }
            else
            {
                Icons.AddAsync(post.ProfileImageUri);//取得
            }

            //文字描画
            //名前描画
            string nameText;
            if (Settings.Instance.NameType == NameTypes.Name)
                nameText = post.User.Name;
            else
                nameText = post.User.Identifier.ScreenName;

            nameText = nameText.Replace('\n', ' ');

            TextRenderer.DrawText(e.Graphics, nameText, font,
                new Rectangle(
                    itemPoint.X + LEFT_SPACE + iconsize + LEFT_SPACE,
                    itemPoint.Y,
                    Settings.Instance.NameWidth,
                    e.Bounds.Height - 1
                ),
                color,
                TextFormatFlags.NoPrefix |
                TextFormatFlags.VerticalCenter |
                TextFormatFlags.EndEllipsis |
                TextFormatFlags.SingleLine
            );

            //内容描画
            var textLeftSpace =
                itemPoint.X + LEFT_SPACE + iconsize + LEFT_SPACE + Settings.Instance.NameWidth + LEFT_SPACE;
            TextRenderer.DrawText(e.Graphics, post.Text.Replace('\n', ' '), font,
                new Rectangle(
                    textLeftSpace,
                    itemPoint.Y,
                    e.Bounds.Width - textLeftSpace,
                    e.Bounds.Height - 1
                ),
                color,
                TextFormatFlags.NoPrefix |
                TextFormatFlags.VerticalCenter |
                TextFormatFlags.WordEllipsis |
                TextFormatFlags.SingleLine
            );

            e.DrawFocusRectangle();
        }
    }
}
