<commit_before>﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Timers;
using BotBits.Events;
using BotBits.SendMessages;

namespace BotBits
{
    public sealed class Chat : EventListenerPackage<Chat>, IDisposable, IChat
    {
        public const int MaxLength = 140;

        private readonly ConcurrentDictionary<string, ChatChannel> _channels
            = new ConcurrentDictionary<string, ChatChannel>();

        private readonly Timer _mySendTimer;
        private bool _warning;

        public int Count
        {
            get
            {
                return this._channels.Sum(c => c.Value.Queue.Count);
            }
        }

        [Obsolete("Invalid to use \"new\" on this class. Use the static .Of(BotBits) method instead.", true)]
        public Chat()
        {
            this._mySendTimer = new Timer(600);
            this._mySendTimer.Elapsed += this.SendTimer_Elapsed;
        }

        public void Say(string msg)
        {
            msg = this.TrimChars(msg);
            new QueueChatEvent(msg)
                .RaiseIn(this.BotBits);
        }

        void IDisposable.Dispose()
        {
            this._mySendTimer.Dispose();
        }

        private void SendTimer_Elapsed(object sender, ElapsedEventArgs elapsedEventArgs)
        {
            this.DoSendTick();
        }
        
        private void DoSendTick()
        {
            foreach (var kv in this._channels.ToArray())
            {
                var channel = kv.Value;

                if (this._warning && channel.LastSent != channel.LastReceived)
                {
                    this.SendChat(this.SplitBypassSend(channel.LastSent, kv.Key != String.Empty).First(), channel);
                }
                else
                {
                    string chatMessage;
                    if (channel.Queue.TryDequeue(out chatMessage))
                    {
                        this.SendChat(chatMessage, channel);
                    }
                    else
                    {
                        this._mySendTimer.Stop();
                    }
                }
            }

            this._warning = false;
        }

        private void SendChat(string message, ChatChannel channel)
        {
            channel.LastSent = message;
            new ChatSendMessage(channel.LastSent)
                .SendIn(this.BotBits);
        }

        private void QueueChat(string msg, bool pm)
        {
            var channel = this.GetChannel(msg, pm);
            this.Enqueue(msg, channel);

            this.InitTimer();
        }

        private void InitTimer()
        {
            if (!this._mySendTimer.Enabled)
            {
                this.DoSendTick();

                this._mySendTimer.Start();
            }
        }

        private string GetChannel(string msg, bool pm)
        {
            string channel = null;
            if (pm) channel = msg.Split(' ').Skip(1).FirstOrDefault();
            return channel ?? string.Empty;
        }


        [EventListener(GlobalPriority.AfterMost)]
        private void OnAfterMost(QueueChatEvent e)
        {
            if (e.Cancelled) return;

            if (e.IsCommand && !e.IsPrivateMessage)
            {
                new ChatSendMessage(this.Truncate(e.Message))
                    .SendIn(this.BotBits);
                return;
            }

            foreach (var msg in this.SplitBypassSend(e.Message, e.IsPrivateMessage))
            {
                this.QueueChat(msg, e.IsPrivateMessage);
            }
        }

        [EventListener]
        private void On(ChatEvent e)
        {
            if (e.Player == Players.Of(this.BotBits).OwnPlayer)
            {
                var channel = this.GetChatChannel("");
                if (channel.LastSent == e.Text) channel.LastReceived = e.Text;
            }
        }

        [EventListener]
        private void On(WriteEvent e)
        {
            if (e.Type == WriteType.ReceivedPrivateMessage)
            {
                var username = e.GetUser();
                var message = e.Text.Substring(0, e.Text.Length - 1); // Bug ingame, space after each private message

                new PrivateMessageEvent(username, message)
                    .RaiseIn(this.BotBits);
            }
            else if (e.Type == WriteType.SentPrivateMessage)
            {
                var username = e.GetUser();
                var message = $"/pm {username} {e.Text.Substring(0, e.Text.Length - 1)}"; // Bug ingame, space after each private message
                
                var channel = this.GetChatChannel(username);
                if (channel.LastSent == message) channel.LastReceived = message;
            }
            else if (e.Type == WriteType.ChattingTooFast)
            {
                this._warning = true;
                this.InitTimer();
            }
            else
            {
                Console.WriteLine(e.Text);
            }
        }

        private void Enqueue(string str, string channel)<commit_msg>Use a better method for trimming the end of pms<commit_after>﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Timers;
using BotBits.Events;
using BotBits.SendMessages;

namespace BotBits
{
    public sealed class Chat : EventListenerPackage<Chat>, IDisposable, IChat
    {
        public const int MaxLength = 140;

        private readonly ConcurrentDictionary<string, ChatChannel> _channels
            = new ConcurrentDictionary<string, ChatChannel>();

        private readonly Timer _mySendTimer;
        private bool _warning;

        public int Count
        {
            get
            {
                return this._channels.Sum(c => c.Value.Queue.Count);
            }
        }

        [Obsolete("Invalid to use \"new\" on this class. Use the static .Of(BotBits) method instead.", true)]
        public Chat()
        {
            this._mySendTimer = new Timer(600);
            this._mySendTimer.Elapsed += this.SendTimer_Elapsed;
        }

        public void Say(string msg)
        {
            msg = this.TrimChars(msg);
            new QueueChatEvent(msg)
                .RaiseIn(this.BotBits);
        }

        void IDisposable.Dispose()
        {
            this._mySendTimer.Dispose();
        }

        private void SendTimer_Elapsed(object sender, ElapsedEventArgs elapsedEventArgs)
        {
            this.DoSendTick();
        }
        
        private void DoSendTick()
        {
            foreach (var kv in this._channels.ToArray())
            {
                var channel = kv.Value;

                if (this._warning && channel.LastSent != channel.LastReceived)
                {
                    this.SendChat(this.SplitBypassSend(channel.LastSent, kv.Key != String.Empty).First(), channel);
                }
                else
                {
                    string chatMessage;
                    if (channel.Queue.TryDequeue(out chatMessage))
                    {
                        this.SendChat(chatMessage, channel);
                    }
                    else
                    {
                        this._mySendTimer.Stop();
                    }
                }
            }

            this._warning = false;
        }

        private void SendChat(string message, ChatChannel channel)
        {
            channel.LastSent = message;
            new ChatSendMessage(channel.LastSent)
                .SendIn(this.BotBits);
        }

        private void QueueChat(string msg, bool pm)
        {
            var channel = this.GetChannel(msg, pm);
            this.Enqueue(msg, channel);

            this.InitTimer();
        }

        private void InitTimer()
        {
            if (!this._mySendTimer.Enabled)
            {
                this.DoSendTick();

                this._mySendTimer.Start();
            }
        }

        private string GetChannel(string msg, bool pm)
        {
            string channel = null;
            if (pm) channel = msg.Split(' ').Skip(1).FirstOrDefault();
            return channel ?? string.Empty;
        }


        [EventListener(GlobalPriority.AfterMost)]
        private void OnAfterMost(QueueChatEvent e)
        {
            if (e.Cancelled) return;

            if (e.IsCommand && !e.IsPrivateMessage)
            {
                new ChatSendMessage(this.Truncate(e.Message))
                    .SendIn(this.BotBits);
                return;
            }

            foreach (var msg in this.SplitBypassSend(e.Message, e.IsPrivateMessage))
            {
                this.QueueChat(msg, e.IsPrivateMessage);
            }
        }

        [EventListener]
        private void On(ChatEvent e)
        {
            if (e.Player == Players.Of(this.BotBits).OwnPlayer)
            {
                var channel = this.GetChatChannel("");
                if (channel.LastSent == e.Text) channel.LastReceived = e.Text;
            }
        }

        [EventListener]
        private void On(WriteEvent e)
        {
            if (e.Type == WriteType.ReceivedPrivateMessage)
            {
                var username = e.GetUser();
                var message = e.Text.TrimEnd(' '); // Bug ingame, space after each private message

                new PrivateMessageEvent(username, message)
                    .RaiseIn(this.BotBits);
            }
            else if (e.Type == WriteType.SentPrivateMessage)
            {
                var username = e.GetUser();
                var message = $"/pm {username} {e.Text.TrimEnd(' ')}"; // Bug ingame, space after each private message
                
                var channel = this.GetChatChannel(username);
                if (channel.LastSent == message) channel.LastReceived = message;
            }
            else if (e.Type == WriteType.ChattingTooFast)
            {
                this._warning = true;
                this.InitTimer();
            }
            else
            {
                Console.WriteLine(e.Text);
            }
        }

        private void Enqueue(string str, string channel)
{'fraction_non_alphanumeric': 0.09113874854255732, 'fraction_numerical': 0.001748931208705791, 'mean_word_length': 1.3629476584022038, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4485457', 'n_tokens_mistral': 2680, 'n_tokens_neox': 2522, 'n_words': 566}