﻿using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using log4net;
using System.Threading;
using TelegramBot;
using Telegram.Bot.Args;
using Telegram.Bot.Types.InlineQueryResults;
using Telegram.Bot.Types.InputMessageContents;
using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.ReplyMarkups;
using Telegram.Bot.Types;
using MagicTheGathering_io;
using MagicTheGathering_io.Queries;
using MagicTheGathering_io.Parameters;
using MagicTheGathering_io.Models;

[assembly: log4net.Config.XmlConfigurator (Watch = true)]

namespace telegram_mtgcard
{
	class MainClass
	{
		static ManualResetEvent _quitEvent = new ManualResetEvent (false);
		static readonly ILog Log = LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType);
		static MtgIoApi _api = new MtgIoApi ();
		static InlineBot _bot = new InlineBot (Log);

		static void Main (string[] args)
		{
			// Log all unhandled exceptions with Log4Net
			AppDomain.CurrentDomain.UnhandledException += (s, e) => {
				var exception = (Exception)e.ExceptionObject;
				Log.Error ("", exception);
			};

			// Event when we quit the application.
			Console.CancelKeyPress += (sender, eArgs) => {
				_quitEvent.Set ();
				eArgs.Cancel = true;
			};

			// Main 'loop'
			MainAsync ().Wait ();

			// Cleanup and quit: Best practice for async console program.
			_quitEvent.WaitOne ();
		}

		static async Task MainAsync ()
		{
			_bot.Initialize ();
			_bot.OnInlineQuery += Bot_OnInlineQuery;
			_bot.StartReceiving ();
		}

		// Whenever an inline query comes in.
		static async void Bot_OnInlineQuery (object sender, InlineQueryEventArgs e)
		{
			string page = e.InlineQuery.Offset == "" ? "1" : e.InlineQuery.Offset;  

			var query = new CardQuery ()
				.Where (MtgParams.NAME, e.InlineQuery.Query)
				.Where (MtgParams.CMC, NumComparison.GREATERTHAN, 3)
				.Where (MtgParams.PAGESIZE, "50")
				.Where (MtgParams.PAGE, page);

			var results = await _api.ExecuteQuery (query);
			var responseList = new List<InlineQueryResult> ();

			foreach (var result in results) {
				responseList.Add (CardToResult (result));
			}
			if (responseList.Count > 0) {
				string newOffset = (Convert.ToInt32 (page) + 1).ToString ();
				await _bot.AnswerInlineQueryAsync (
					e.InlineQuery.Id, 
					responseList.ToArray (), 
					default (int?), 
					false, 
					newOffset,
					"Go to advanced search",
					"advanced"
				);
			}
		}

		// Create an 'InlineQueryResult' from Card information.
		static InlineQueryResult CardToResult (Card card)
		{
			return new InlineQueryResultArticle () {
				Id = card.Id,
				Title = card.Name + " (" + card.Set + ")",
				Description = card.Type,
				InputMessageContent = BuildMessageContent (card),
				ReplyMarkup = BuildKeyboard (card),
				Url = card.Website,
				HideUrl = true,
				ThumbUrl = card.ImageUrl
			};
		}

		// Create the message content for when a user clicks a result.
		static InputMessageContent BuildMessageContent (Card card)
		{
			if (card.ImageUrl != null) {
				return new InputTextMessageContent () {
					MessageText = card.ImageUrl
				};
			} else {
				return new InputTextMessageContent () {
					MessageText = card.ToMarkdownString (),
					ParseMode = ParseMode.Markdown,
					DisableWebPagePreview = false
				};
			}

		}

		// Build the 'keyboard' that appears underneath a result.
		static InlineKeyboardMarkup BuildKeyboard (Card card)
		{
			var row = new List<InlineKeyboardButton> ();
			row.Add (new InlineKeyboardButton () {
				Text = "Check on the Gatherer!",
				Url = card.Website
			});
			return new InlineKeyboardMarkup (row.ToArray ());
		}

	}
}
