context: using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Linq;
  using System.Text.RegularExpressions;
  using System.Threading.Tasks;
  using System.Xml.Linq;
  using Database;
  using Telegram.Bot.Exceptions;
  using Telegram.Bot.Types;
  using Telegram.Bot.Types.Enums;
  using Telegram.Bot.Types.ReplyMarkups;
  using Werewolf_Control.Attributes;
  using Werewolf_Control.Handler;
  using Werewolf_Control.Helpers;
  
  namespace Werewolf_Control
  {
      public static partial class Commands
      {
          [Command(Trigger = "smite", GroupAdminOnly = true, Blockable = true, InGroupOnly = true)]
          public static void Smite(Update u, string[] args)
          {
              //if (u.Message.ReplyToMessage == null)
              //{
              //    Bot.Send(GetLocaleString("MustReplySmite",GetLanguage(u.Message.Chat.Id)).ToBold(), u.Message.Chat.Id);
              //    return;
              //}
  
              //check for reply
              if (u.Message.ReplyToMessage != null)
                  //smite sender
                  Bot.GetGroupNodeAndGame(u.Message.Chat.Id)?.SmitePlayer(u.Message.ReplyToMessage.From.Id);
  
              //get the names to smite
              foreach (var e in u.Message.Entities)
              {
                  switch (e.Type)
                  {
                      case MessageEntityType.Mention:
                          //get user
                          var username = u.Message.Text.Substring(e.Offset + 1, e.Length - 1);
                          using (var db = new WWContext())
                          {
                              var id = db.Players.FirstOrDefault(x => x.UserName == username)?.TelegramId ?? 0;
                              if (id != 0)
                                  Bot.GetGroupNodeAndGame(u.Message.Chat.Id)?.SmitePlayer(id);
                          }
                          break;
                      case MessageEntityType.TextMention:
                          Bot.GetGroupNodeAndGame(u.Message.Chat.Id)?.SmitePlayer(e.User.Id);
                          break;
                  }
              }
  
              var did = 0;
              if (int.TryParse(args[1], out did))
                  Bot.GetGroupNodeAndGame(u.Message.Chat.Id)?.SmitePlayer(did);
  
          }
  
          [Command(Trigger = "config", GroupAdminOnly = true, InGroupOnly = true)]
          public static void Config(Update update, string[] args)
          {
              var id = update.Message.Chat.Id;
  
              //make sure the group is in the database
              using (var db = new WWContext())
              {
                  var grp = db.Groups.FirstOrDefault(x => x.GroupId == id);
                  if (grp == null)
                  {
                      grp = MakeDefaultGroup(id, update.Message.Chat.Title, "config");
                      db.Groups.Add(grp);
                  }
  
                  grp.BotInGroup = true;
                  grp.UserName = update.Message.Chat.Username;
                  grp.Name = update.Message.Chat.Title;
                  grp.UpdateFlags();
                  db.SaveChanges();
              }
  
              var menu = UpdateHandler.GetConfigMenu(update.Message.Chat.Id);
              Bot.Api.SendTextMessage(update.Message.From.Id, GetLocaleString("WhatToDo", GetLanguage(update.Message.From.Id)),
                  replyMarkup: menu);
          }
  
          [Command(Trigger = "uploadlang", GlobalAdminOnly = true)]
          public static void UploadLang(Update update, string[] args)
          {
              try
              {
                  var id = update.Message.Chat.Id;
                  if (update.Message.ReplyToMessage?.Type != MessageType.DocumentMessage)
                  {
                      Send("Please reply to the file with /uploadlang", id);
                      return;
                  }
                  var fileid = update.Message.ReplyToMessage.Document?.FileId;
                  if (fileid != null)
                      LanguageHelper.UploadFile(fileid, id,
                          update.Message.ReplyToMessage.Document.FileName,
                          update.Message.MessageId);
              }
              catch (Exception e)
              {
                  Bot.Api.SendTextMessage(update.Message.Chat.Id, e.Message, parseMode: ParseMode.Default);
              }
          }
  
          [Command(Trigger = "getban", GlobalAdminOnly = true)]
          public static void GetUserStatus(Update u, string[] a)
          {
              using (var db = new WWContext())
              {
                  var p = u.GetTarget(db);
                  var ban = db.GlobalBans.FirstOrDefault(x => x.TelegramId == p.TelegramId);
                  var status = "";
                  if (ban != null)
                  {
                      status = $"<b>Banned for: {ban.Reason}</b>\nBy: {ban.BannedBy} on {ban.BanDate?.ToString("ddMMMyyyy H:mm:ss zzz").ToUpper()}\n";
                      var expire = (ban.Expires - DateTime.Now);
                      if (expire > TimeSpan.FromDays(365))
                      {
                          status += "<b>Perm Ban</b>";
                      }
                      else
                      {
                          status += String.Format("Ban expiration: <b>{0:%d} days, {0:%h} hours, {0:%m} minutes</b>", expire);
                      }
                  }
                  else
                      status = "Not banned (in Werewolf)";
                  var firstSeen = p.GamePlayers?.OrderBy(x => x.GameId).FirstOrDefault()?.Game?.TimeStarted;
                  
                  Bot.Api.SendTextMessage(u.Message.Chat.Id, $"Player: {p.Name.FormatHTML()}\nCurrent Status: {status}\nPlayer first seen: {(firstSeen?.ToString("ddMMMyyyy H:mm:ss zzz").ToUpper() ??"Hasn't played ever!")}", disableWebPagePreview: true, replyToMessageId: u.Message.MessageId, parseMode: ParseMode.Html);
              }
  
          }
  
          [Command(Trigger = "validatelangs", GlobalAdminOnly = true)]
          public static void ValidateLangs(Update update, string[] args)
          {
              //var langs = Directory.GetFiles(Bot.LanguageDirectory)
              //                                            .Select(x => XDocument.Load(x)
              //                                                        .Descendants("language")
              //                                                        .First()
              //                                                        .Attribute("name")
              //                                                        .Value
              //                                            ).ToList();
              //langs.Insert(0, "All");
  
              //var buttons =
              //    langs.Select(x => new[] { new InlineKeyboardButton(x, $"validate|{update.Message.Chat.Id}|{x}") }).ToArray();
              //var menu = new InlineKeyboardMarkup(buttons.ToArray());
              //Bot.Api.SendTextMessage(update.Message.Chat.Id, "Validate which language?",
              //    replyToMessageId: update.Message.MessageId, replyMarkup: menu);
  
  
              var langs = Directory.GetFiles(Bot.LanguageDirectory, "*.xml").Select(x => new LangFile(x)).ToList();
  
  
              List<InlineKeyboardButton> buttons = langs.Select(x => x.Base).Distinct().OrderBy(x => x).Select(x => new InlineKeyboardButton(x, $"validate|{update.Message.From.Id}|{x}|null|base")).ToList();
              //buttons.Insert(0, new InlineKeyboardButton("All", $"validate|{update.Message.From.Id}|All|null|base"));
  
              var baseMenu = new List<InlineKeyboardButton[]>();
              for (var i = 0; i < buttons.Count; i++)
              {
                  if (buttons.Count - 1 == i)
                  {
                      baseMenu.Add(new[] { buttons[i] });
                  }
                  else
                      baseMenu.Add(new[] { buttons[i], buttons[i + 1] });
                  i++;
              }
  
              var menu = new InlineKeyboardMarkup(baseMenu.ToArray());
              try
              {
                  Bot.Api.SendTextMessage(update.Message.Chat.Id, "Validate which language?",
                      replyToMessageId: update.Message.MessageId, replyMarkup: menu);
              }
              catch (AggregateException e)
              {
                  foreach (var ex in e.InnerExceptions)
                  {
                      var x = ex as ApiRequestException;
  
                      Send(x.Message, update.Message.Chat.Id);
                  }
              }
              catch (ApiRequestException ex)
              {
                  Send(ex.Message, update.Message.Chat.Id);
              }
          }
  
  
          [Command(Trigger = "getidles", GroupAdminOnly = true)]
          public static void GetIdles(Update update, string[] args)
          {
              //check user ids and such
              List<int> ids = new List<int>();
              foreach (var arg in args.Skip(1).FirstOrDefault()?.Split(' ') ?? new[] { "" })
              {
                  var id = 0;
                  if (int.TryParse(arg, out id))
                  {
                      ids.Add(id);
                  }
              }
  
              //now check for mentions
              foreach (var ent in update.Message.Entities.Where(x => x.Type == MessageEntityType.TextMention))
              {
                  ids.Add(ent.User.Id);
              }
  
              //check for reply
  
gt:             if (update.Message.ReplyToMessage != null)