context: using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.Globalization;
  using System.Linq;
  using System.Text.RegularExpressions;
  using System.Windows.Forms;
  using LobbyClient;
  using ZeroKLobby;
  using ZeroKLobby.Controls;
  using ZeroKLobby.Lines;
  using ZeroKLobby.Notifications;
  using ZkData;
  
  namespace ZeroKLobby.MicroLobby
  {
  
      public partial class ChatTab : ZklBaseControl, INavigatable
      {
          BattleChatControl battleChatControl;
          readonly ToolTabs toolTabs = new ToolTabs { Dock = DockStyle.Fill };
          string focusWhenJoin;
  
  
          private void InitializeComponent()
          {
              this.SuspendLayout();
              // 
              // ChatTab
              // 
              this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
              this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
              this.Margin = new System.Windows.Forms.Padding(0);
              this.Padding = new System.Windows.Forms.Padding(0);
              this.Name = "ChatTab";
              this.Size = new System.Drawing.Size(596, 444);
              this.ResumeLayout(false);
  
          }
  
  
          public ChatTab()
          {
              SuspendLayout();
              InitializeComponent();
              if (Process.GetCurrentProcess().ProcessName == "devenv") return; // detect design mode, workaround for non-working this.DesignMode 
              Controls.Add(toolTabs);
  
              AddBattleControl();
  
              Program.TasClient.ChannelJoined += client_ChannelJoined;
              Program.TasClient.Said += client_Said;
              Program.TasClient.ConnectionLost += TasClient_ConnectionLost;
              Program.TasClient.ChannelLeft += TasClient_ChannelLeft;
              Program.TasClient.LoginAccepted += TasClient_LoginAccepted;
              Program.TasClient.UserRemoved += TasClient_UserRemoved;
              Program.TasClient.UserAdded += TasClient_UserAdded;
              Program.TasClient.FriendListUpdated += TasClientOnFriendListUpdated;
              Program.TasClient.ChannelJoinFailed += TasClient_ChannelJoinFailed;
  
              foreach (var channel in Program.TasClient.JoinedChannels.Values) CreateChannelControl(channel.Name);
              toolTabs.SelectChannelTab("Battle");
              ResumeLayout();
          }
  
          private void TasClientOnFriendListUpdated(object sender, IReadOnlyCollection<string> friends)
          {
              foreach (var friend in friends)
              {
                  if (GetPrivateMessageControl(friend) == null)
                  {
                      CreatePrivateMessageControl(friend);
                      //toolTabs.SelectPrivateTab(friend);
                  }
              }
          }
  
          public void CloseChannelTab(string key)
          {
              toolTabs.RemoveChannelTab(key);
          }
  
          public void ClosePrivateTab(string key)
          {
              toolTabs.RemovePrivateTab(key);
          }
  
  
          public PrivateMessageControl CreatePrivateMessageControl(string userName)
          {
              var pmControl = new PrivateMessageControl(userName) { Dock = DockStyle.Fill };
              var isFriend = Program.TasClient.Friends.Contains(userName);
              User user;
              var isOffline = !Program.TasClient.ExistingUsers.TryGetValue(userName, out user);
              var icon = isOffline ? ZklResources.grayuser : TextImage.GetUserImage(userName);
              var contextMenu = new ContextMenu();
              if (!isFriend)
              {
                  var closeButton = new MenuItem();
                  closeButton.Click += (s, e) => toolTabs.RemovePrivateTab(userName);
                  contextMenu.MenuItems.Add(closeButton);
              }
              toolTabs.AddTab(userName, userName, pmControl, icon, ToolTipHandler.GetUserToolTipString(userName), 0);
              pmControl.ChatLine +=
                  (s, e) =>
                  {
                      if (Program.TasClient.IsLoggedIn)
                      {
                          Program.TasClient.Say(SayPlace.User, userName, e.Data, false);
                      }
                  };
              return pmControl;
          }
  
  
          public void OpenChannel(string channelName)
          {
              if (GetChannelControl(channelName) != null) toolTabs.SelectChannelTab(channelName);
              else
              {
                  focusWhenJoin = channelName;
                  Program.TasClient.JoinChannel(channelName);
              }
          }
  
          public void OpenPrivateMessageChannel(string userName)
          {
              if (GetPrivateMessageControl(userName) == null) CreatePrivateMessageControl(userName);
              toolTabs.SelectPrivateTab(userName);
          }
  
          public string GetNextTabPath()
          {
              return toolTabs.GetNextTabPath();
          }
          public string GetPrevTabPath()
          {
              return toolTabs.GetPrevTabPath();
          }
  
  
  
  
          void AddBattleControl()
          {
              if (battleChatControl == null || battleChatControl.IsDisposed) battleChatControl = new BattleChatControl { Dock = DockStyle.Fill };
              if (toolTabs.GetChannelTab("Battle") == null) toolTabs.AddTab("Battle", "Battle", battleChatControl, ZklResources.game, "Current battle room", 3);
          }
  
  
          ChatControl CreateChannelControl(string channelName)
          {
              var existing = GetChannelControl(channelName);
              if (existing != null) return existing;
              var chatControl = new ChatControl(channelName) { Dock = DockStyle.Fill };
              var gameInfo = KnownGames.List.FirstOrDefault(x => x.Channel == channelName);
  
              if (gameInfo != null) toolTabs.AddTab(channelName, gameInfo.FullName, chatControl, ZklResources.chat, null, 2);
              else toolTabs.AddTab(channelName, channelName, chatControl, ZklResources.chat, null, 1);
              chatControl.ChatLine += (s, e) => Program.TasClient.Say(SayPlace.Channel, channelName, e.Data, false);
              return chatControl;
          }
  
          public ChatControl GetChannelControl(string channelName)
          {
              return toolTabs.GetChannelTab(channelName);
          }
  
          PrivateMessageControl GetPrivateMessageControl(string userName)
          {
              return toolTabs.GetPrivateTab(userName);
          }
  
  
          void client_ChannelJoined(object sender, Channel channel)
          {
              var channelName = channel.Name;
              CreateChannelControl(channelName);
              if (focusWhenJoin == channelName)
              {
                  toolTabs.SelectChannelTab(channelName);
                  focusWhenJoin = null;
              }
          }
  
          void client_Said(object sender, TasSayEventArgs e)
          {
              var tas = (TasClient)sender;
              if (Program.TasClient.Ignores.Contains(e.UserName))
              {
                  return;
              }
  
              if (e.Place == SayPlace.Battle && !e.IsEmote && !Program.TasClient.MyUser.IsInGame) Program.MainWindow.NotifyUser("chat/battle", null);
              if (e.Place == SayPlace.Channel) Program.MainWindow.NotifyUser("chat/channel/" + e.Channel, null);
              else if (e.Place == SayPlace.User)
              {
                  var otherUserName = e.UserName == tas.UserName ? e.Channel : e.UserName;
  
                  var pmControl = GetPrivateMessageControl(otherUserName);
                  // block non friend messages 
                  if (pmControl == null && Program.Conf.BlockNonFriendPm && !Program.TasClient.Friends.Contains(otherUserName) && !Program.TasClient.ExistingUsers[e.UserName].IsBot)
                  {
                      if (e.UserName != Program.TasClient.UserName)
                          Program.TasClient.Say(SayPlace.User,
                                                otherUserName,
                                                "Sorry, I'm busy and do not receive messages. If you want to ask something, use #zk channel. If you have issue to report use https://github.com/ZeroK-RTS/Zero-K/issues",
                                                false);
                  }
                  else
                  {
                      pmControl = pmControl ?? CreatePrivateMessageControl(otherUserName);
                      if (!e.IsEmote) pmControl.AddLine(new SaidLine(e.UserName, e.Text, e.Time));
                      else pmControl.AddLine(new SaidExLine(e.UserName, e.Text, e.Time));
                      if (e.UserName != Program.TasClient.MyUser.Name)
                      {
                          MainWindow.Instance.NotifyUser("chat/user/" + otherUserName,
                                                         string.Format("{0}: {1}", otherUserName, e.Text),
                                                         false,
                                                         true);
                      }
                  }
  
  
              }
              else if (e.Place == SayPlace.MessageBox) Trace.TraceInformation("TASC: {0}", e.Text);
              if (e.Place == SayPlace.MessageBox) WarningBar.DisplayWarning(e.Text);
          }
  
  
          void TasClient_ChannelJoinFailed(object sender, JoinChannelResponse joinChannelResponse)
          {
              WarningBar.DisplayWarning("Channel Joining Error - " + joinChannelResponse.Reason);
          }
  
  
          void TasClient_ChannelLeft(object sender, Channel channel)
          {
              var channelName = channel.Name;
              var chatControl = GetChannelControl(channelName);
              toolTabs.RemoveChannelTab(channelName);
              if (chatControl != null)
              {
                  chatControl.Reset();
                  chatControl.Dispose();
              }
          }
  
  
          void TasClient_ConnectionLost(object sender, TasEventArgs e)
          {
              toolTabs.DisposeAllTabs();
              AddBattleControl();
          }
  
          void TasClient_LoginAccepted(object sender, TasEventArgs e)
          {
              AddBattleControl();
              foreach (var friendName in Program.TasClient.Friends) CreatePrivateMessageControl(friendName);
              foreach (var channel in Program.AutoJoinManager.Channels) Program.TasClient.JoinChannel(channel, Program.AutoJoinManager.GetPassword(channel));
              var lang = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
              if (!string.IsNullOrEmpty(lang)) Program.TasClient.JoinChannel(lang);
          }
  
          void TasClient_UserAdded(object sender, User user)
          {
              var userName = user.Name;
              var pmControl = GetPrivateMessageControl(userName);
              if (pmControl != null)
                  toolTabs.SetIcon(userName, Program.TasClient.Friends.Contains(userName) ? ZklResources.friend : TextImage.GetUserImage(userName),
                      true);
          }
  
          void TasClient_UserRemoved(object sender, UserDisconnected e)
          {
              var userName = e.Name;
  
gt:             var pmControl = GetPrivateMessageControl(userName);