//public ChatHandler(ChatVideo cv, BTTV bttv, FFZ ffz, Badges badges, Bits bits)
 public ChatHandler(ChatVideo cv, Badges badges, Bits bits)
 {
     Font       = (Font)cv.Font.Clone();
     BoldFont   = new Font(Font, FontStyle.Bold);
     ChatColor  = Color.FromArgb(cv.ChatColor.A, cv.ChatColor.R, cv.ChatColor.G, cv.ChatColor.B);
     BGColor    = Color.FromArgb(cv.BGColor.A, cv.BGColor.R, cv.BGColor.G, cv.BGColor.B);
     Width      = cv.Width;
     Spacing    = cv.LineSpacing;
     ShowBadges = cv.ShowBadges;
     //BTTV = bttv;
     //FFZ = ffz;
     Badges = badges;
     Bits   = bits;
 }
        public DrawableMessage MakeDrawableMessage(ChatMessage message)
        {
            var lines = new List <Line>();

            // \p{Cs} or \p{Surrogate}: one half of a surrogate pair in UTF-16 encoding.
            var words = Regex.Replace(message.Text, @"\p{Cs}\p{Cs}", m =>
            {
                message.Emotes?.Where(e => e.Begin > m.Index)?.ToList().ForEach(e2 => e2.Begin += 1);
                return(Emoji.Exists(m.Value) ? ' ' + m.Value + ' ' : "?");
            }).Split(' ').Where(s => s != string.Empty);

            var builder = new StringBuilder();

            float x = ChatVideo.HorizontalPad;
            float y = 0;
            float maximum_y_offset = 0;

            int cursor = 0;

            List <Drawable> dl = new List <Drawable>();

            var user_tag  = message.Name + ": ";
            var user_size = MeasureText(user_tag, BoldFont, (int)Width);

            if (ShowBadges)
            {
                message.Badges?.ForEach(b =>
                {
                    var img = Badges?.Lookup(b.ID, b.Version);
                    if (img != null)
                    {
                        var align_vertical = user_size.Height * .5f - img.Height * .5f;
                        if (align_vertical < 0)
                        {
                            maximum_y_offset = Math.Max(Math.Abs(align_vertical), maximum_y_offset);
                        }
                        var badge = new Badge(x, align_vertical, img);
                        dl.Add(badge);
                        x += img.Width + ChatVideo.BadgePad;
                    }
                });
            }

            var color = Colors.GetCorrected(message.Color, BGColor, message.Name);

            dl.Add(new User(x, y, user_size.Height, user_tag, color, BoldFont));
            x += user_size.Width;

            Action new_line = delegate
            {
                y += maximum_y_offset;
                var line = new Line(ChatVideo.HorizontalPad, y, Font.Height + maximum_y_offset, dl);
                lines.Add(line);
                y += maximum_y_offset + line.Height;
                maximum_y_offset = 0;
                dl = new List <Drawable>();
                x  = ChatVideo.HorizontalPad;
            };

            Action empty_builder = delegate
            {
                var txt = builder.ToString();
                var sz  = MeasureText(txt, Font, (int)Width);
                dl.Add(new Text(x, 0, sz.Height, txt, ChatColor, Font));
                builder.Clear();
                x += sz.Width;
            };

            foreach (var word in words)
            {
                var emote = Emoji.GetEmoji(word) ?? //FFZ?.GetEmote(word) ?? BTTV?.GetEmote(word) ??
                            TwitchEmote.GetEmote(message.Emotes?.FirstOrDefault(e => e.Begin == cursor)?.ID);

                cursor += word.Length + 1;

                if (emote != null)
                {
                    if (builder.Length > 0)
                    {
                        builder.Append(' ');
                        empty_builder();
                    }

                    if (x + emote.Width + 2 * ChatVideo.HorizontalPad > Width)
                    {
                        new_line();
                    }

                    var align_vertical = Font.Height * .5f - emote.Height * .5f;
                    if (align_vertical < 0)
                    {
                        maximum_y_offset = Math.Max(Math.Abs(align_vertical), maximum_y_offset);
                    }
                    x += ChatVideo.EmotePad;
                    dl.Add(new Emote(x, align_vertical, emote));
                    x += emote.Width;

                    continue;
                }

                var cheer = message.Content.Bits > 0 ? Bits?.GetCheer(word) : default(Bits.Cheer);

                if (cheer?.Amount > 0)
                {
                    var ch = cheer.Value;

                    if (builder.Length > 0)
                    {
                        builder.Append(' ');
                        empty_builder();
                    }

                    if (x + ch.Emote.Width + 2 * ChatVideo.HorizontalPad > Width)
                    {
                        new_line();
                    }

                    var align_vertical = Font.Height * .5f - ch.Emote.Height * .5f;
                    if (align_vertical < 0)
                    {
                        maximum_y_offset = Math.Max(Math.Abs(align_vertical), maximum_y_offset);
                    }
                    x += ChatVideo.EmotePad;
                    dl.Add(new Emote(x, align_vertical, ch.Emote));
                    x += ch.Emote.Width;

                    var cheer_amount = cheer?.Amount.ToString();
                    var sz           = MeasureText(cheer_amount, Font, (int)Width);
                    if (x + sz.Width + 2 * ChatVideo.HorizontalPad >= Width)
                    {
                        new_line();
                    }
                    dl.Add(new Text(x, 0, sz.Height, cheer_amount, ch.Color, Font));
                    x += sz.Width;
                    continue;
                }

                var text     = builder.ToString();
                var word_tag = word + ' ';
                var size     = MeasureText(text + word_tag, Font, (int)Width);
                if (x + size.Width + 2 * ChatVideo.HorizontalPad >= Width)
                {
                    empty_builder();
                    new_line();
                    builder.Append(word_tag);
                }
                else
                {
                    builder.Append(word_tag);
                }
            }

            if (builder.Length > 0)
            {
                var text = builder.ToString();
                var size = MeasureText(text, Font, (int)Width);
                dl.Add(new Text(x, 0, size.Height, text, ChatColor, Font));
            }

            if (dl.Count > 0)
            {
                lines.Add(new Line(ChatVideo.HorizontalPad, y + maximum_y_offset, Font.Height + maximum_y_offset, dl));
            }

            return(new DrawableMessage {
                Lines = lines,
                StartFrame = (uint)(message.TimeOffset * ChatVideo.FPS),
                Live = message.Source == "chat",
            });
        }