context: using System;
  using System.Diagnostics;
  using System.Globalization;
  using System.Linq;
  using System.Text.RegularExpressions;
  using System.Windows.Forms;
  using LobbyClient;
  using ZeroKLobby;
  using ZeroKLobby.Lines;
  using ZeroKLobby.Notifications;
  using ZkData;
  
  namespace ZeroKLobby.MicroLobby
  {
  
      public partial class ChatTab : UserControl, INavigatable
      {
          BattleChatControl battleChatControl;
          readonly ToolTabs toolTabs = new ToolTabs { Dock = DockStyle.Fill };
          string focusWhenJoin;
  
  
  
  
          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.FriendManager.FriendAdded += FriendManager_FriendAdded;
              Program.FriendManager.FriendRemoved += FriendManager_FriendRemoved;
              Program.TasClient.ChannelJoinFailed += TasClient_ChannelJoinFailed;
  
              foreach (var channel in Program.TasClient.JoinedChannels.Values.Where(c => !IsIgnoredChannel(c.Name))) CreateChannelControl(channel.Name);
              toolTabs.SelectChannelTab("Battle");
              ResumeLayout();
          }
  
          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.FriendManager.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)
                      {
                          if (Program.TasClient.ExistingUsers.ContainsKey(userName)) Program.TasClient.Say(SayPlace.User, userName, e.Data, false);
                          else Program.TasClient.Say(SayPlace.User, GlobalConst.NightwatchName, e.Data, false, string.Format("!pm {0} ", userName)); // send using PM
                      }
                  };
              return pmControl;
          }
  
          public static bool IsIgnoredChannel(string channelName)
          {
              return false;
          }
  
          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.battle, "Current battle room", 3);
          }
  
  
          ChatControl CreateChannelControl(string channelName)
          {
              if (IsIgnoredChannel(channelName)) return null;
              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.game, 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.Conf.IgnoredUsers.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 && !IsIgnoredChannel(e.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;
  
                  // support for offline pm and persistent channels 
                  if (otherUserName == GlobalConst.NightwatchName && e.Text.StartsWith("!pm"))
                  {
                      // message received
                      if (e.UserName == GlobalConst.NightwatchName)
                      {
                          var regex = Regex.Match(e.Text, "!pm\\|([^\\|]*)\\|([^\\|]+)\\|([^\\|]+)\\|([^\\|]+)");
                          if (regex.Success)
                          {
                              var chan = regex.Groups[1].Value;
                              var name = regex.Groups[2].Value;
                              var time = DateTime.Parse(regex.Groups[3].Value, CultureInfo.InvariantCulture).ToLocalTime();
                              var text = regex.Groups[4].Value;
  
                              if (string.IsNullOrEmpty(chan))
                              {
                                  var pmControl = GetPrivateMessageControl(name) ?? CreatePrivateMessageControl(name);
                                  pmControl.AddLine(new SaidLine(name, text, time));
                                  MainWindow.Instance.NotifyUser("chat/user/" + name, string.Format("{0}: {1}", name, text), false, true);
                              }
                              else
                              {
                                  var chatControl = GetChannelControl(chan) ?? CreateChannelControl(chan);
                                  chatControl.AddLine(new SaidLine(name, text, time));
                                  Program.MainWindow.NotifyUser("chat/channel/" + chan, null);
                              }
                          }
                          else
                          {
                              Trace.TraceWarning("Incomprehensible Nightwatch message: {0}", e.Text);
                          }
                      }
                      else // message sent to nightwatch
                      {
                          var regex = Regex.Match(e.Text, "!pm ([^ ]+) (.*)");
                          if (regex.Success)
                          {
                              var name = regex.Groups[1].Value;
                              var text = regex.Groups[2].Value;
                              var pmControl = GetPrivateMessageControl(name) ?? CreatePrivateMessageControl(name);
                              pmControl.AddLine(new SaidLine(Program.Conf.LobbyPlayerName, text));
                          }
                      }
                  }
                  else
                  {
  
                      var pmControl = GetPrivateMessageControl(otherUserName);
                      // block non friend messages 
                      if (pmControl == null && Program.Conf.BlockNonFriendPm && !Program.FriendManager.Friends.Contains(otherUserName) && !Program.TasClient.ExistingUsers[e.UserName].IsBot)
                      {
  
gt:                         if (e.UserName != Program.TasClient.UserName)