context: using Microsoft.Extensions.Configuration;
  using Microsoft.Extensions.Logging;
  using Newtonsoft.Json;
  using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Linq;
  using System.Text;
  using System.Threading;
  using System.Threading.Tasks;
  using Telegram.Bot;
  using Telegram.Bot.Args;
  using Telegram.Bot.Types;
  using Telegram.Bot.Types.Enums;
  using TelegramBotCore.Instagram;
  using TelegramBotCore.NetizenBuzz;
  
  namespace TelegramBot
  {
      public partial class Program
      {
          public static IConfigurationRoot Configuration { get; set; }
  
          private static TelegramBotClient Bot;
  
          private static NetizenBuzzService NetizenBuzzServant;
          private static InstagramService InstagramServant;
          private static AKPService AKPServant;
          private static HashSet<string> InstagramNameList;
          private static HashSet<string> Admins;
          private static HashSet<string> Blocked;
          private static Dictionary<string, string> Aliases;
          private static bool NetizensBuzzUpdatesOn;
          private static bool AKPBuzzUpdatesOn;
          private static readonly HashSet<long> ChatIdList = new HashSet<long>();
  
          private static ILoggerFactory loggerFactory = new LoggerFactory()
          .AddConsole()
          .AddDebug();
          private static ILogger logger = loggerFactory.CreateLogger<Program>();
          static void Main(string[] args)
          {
              logger.LogInformation("Program Beginning");
              var builder = new ConfigurationBuilder()
              .SetBasePath(Directory.GetCurrentDirectory())
              .AddJsonFile("Resources/settings.json");
  
              Configuration = builder.Build();
  
              Bot = new TelegramBotClient(Configuration["BotAuthToken"]);
              NetizensBuzzUpdatesOn = bool.Parse(Configuration["GetNetizensBuzzUpdates"]);
              AKPBuzzUpdatesOn = bool.Parse(Configuration["GetAKPBuzzUpdates"]);
              
              InstagramServant = new InstagramService();
              NetizenBuzzServant = new NetizenBuzzService();
              AKPServant = new AKPService();
  
              InstagramNameList = JsonConvert.DeserializeObject<HashSet<string>>(System.IO.File.ReadAllText(Configuration["InstagramAccountListPath"]));
              Admins = JsonConvert.DeserializeObject<HashSet<string>>(System.IO.File.ReadAllText(Configuration["AdminListPath"]));
              Blocked = JsonConvert.DeserializeObject<HashSet<string>>(System.IO.File.ReadAllText(Configuration["BlockedListPath"]));
              Aliases = JsonConvert.DeserializeObject<Dictionary<string, string>>(System.IO.File.ReadAllText(Configuration["InstagramAliasListPath"]));
              
              Bot.OnMessage += OnMessageRecieved;
              InstagramServant.NewContentRecieved += OnInstagramContentUpdate;
              NetizenBuzzServant.NewNetizenBuzzPost += OnNetizenBuzzUpdate;
              AKPServant.NewAKPArticle += OnAKPUpdate;
  
              Bot.StartReceiving();
              InstagramServant.Start(InstagramNameList.ToList<string>(), 120000);
              
              if (NetizensBuzzUpdatesOn)
              {
                  Task.Run(() => NetizenBuzzServant.Start());
              }
  
              if (AKPBuzzUpdatesOn)
              {
                  Task.Run(() => AKPServant.Start());
              }
  
              while (true)
              {
                  System.Threading.Thread.Sleep(5000);
              }
          }
  
          private static async void OnInstagramContentUpdate(object sender, OnNewContentRecievedEventArgs args)
          {
              if (args.UserInfo.items.Count == 0) // someone deleted all of their posts...
              {
                  return;
              }
  
              var item = args.UserInfo.items[0];
              var username = args.Username;
              var PostType = item.type;
  
              // find an alias if there is one
              foreach (var key in Aliases.Keys)
              {
                  if (Aliases[key] == username)
                  {
                      username = key;
                  }
              }
  
              foreach(var chatId in ChatIdList)
              {
                  string sendThis = "";
  
                  sendThis += item.link + " by " + username + "\n";
  
                  if (PostType == UserItemTypeEnum.Types.carousel.ToString())
                  {
                      string singleOrPluralItem = (item.carousel_media.Count() - 1) == 1 ? "item" : "items";
                      sendThis += "+ " + (item.carousel_media.Count()-1) + " " + singleOrPluralItem;
                  }
  
                  try
                  {
                      await Bot.SendTextMessageAsync(chatId, sendThis);
                  } catch (Exception e)
                  {
                      logger.LogError(e.ToString());
  
                      if (ChatIdList.Contains(chatId))
                      {
                          ChatIdList.Remove(chatId);
                      }
                      continue;
                  }
  
                  System.Threading.Thread.Sleep(1000);
              }
          }
  
  
          private static async void SendInstagramPostLink(ChatId chatId, Item item)
          {
              await Bot.SendTextMessageAsync(chatId, item.link);
          }
  
          private static async void OnNetizenBuzzUpdate(object sender, OnNewNetizenBuzzPostEventArgs args)
          {
              string link = args.NewPost;
              
              foreach (var chatId in ChatIdList)
              {
                  try
                  {
                      await Bot.SendTextMessageAsync(chatId, link);
                  }catch (Exception e)
                  {
                      ChatIdList.Remove(chatId);
                      logger.LogError(e.ToString());
                      continue;
                  }
              }
          }
  
          private static async void OnAKPUpdate(object sender, OnNewAKPArticleEventArgs args)
          {
              string link = args.NewArticle;
              foreach (var chatId in ChatIdList)
              {
                  await Bot.SendTextMessageAsync(chatId, link);
              }
          }
          private static async void OnMessageRecieved(object sender, MessageEventArgs args)
          {
              logger.LogInformation("message recieved");
              Message message = args.Message;
              if (message.Type != MessageType.TextMessage)
              {
                  return;
              }
  
              var ChatId = message.Chat.Id;
              var username = message.Chat.Username;
              var messagecontent = message.Text;
  
              if (Blocked.Contains(username))
              {
                  await Bot.SendTextMessageAsync(ChatId, "\"No\"");
                  return;
              }
              if (!ChatIdList.Contains(ChatId))
              {
                  logger.LogInformation("New Chat discovered " + ChatId);
                  ChatIdList.Add(ChatId);
              }
              if (messagecontent.StartsWith("/updateme"))
              {
                  logger.LogInformation("I have been invited to update " + ChatId);
                  ChatIdList.Add(ChatId);
              }
  
              if (messagecontent.StartsWith("/addinsta"))
              {
                  string[] command = messagecontent.Split(' ');
                  if (command.Length != 2)
                  {
                      await Bot.SendTextMessageAsync(ChatId, "Invalid Arguments for /addInsta");
                      return;
                  }
  
                  string name = command[1];
                  logger.LogInformation("addinsta initiated by " + username);
  
                  try
                  {
                      await InstagramServant.AddToFollowList(name);
                  }
                  catch (Exception e)
                  {
                      Console.WriteLine(e);
  
gt:                     await Bot.SendTextMessageAsync(ChatId, "Failed to add account");