using Concilium.Helpers;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace Concilium.Bot.Features
{
    [BotFeature(".googlefight")]
    [BotFeature(".google")]
    [BotFeature(".googleimage")]
    public class GoogleFeature : BotFeatureBase
    {
        public override void Execute(string _sCommand, string _sSource, string _sTarget, string _sMessage, IList<string> _parameters, string _ip)
        {
            string sReply = null;
            if (_sCommand == ".googlefight")
                sReply = ProcessChatGoogleFight(_parameters, _ip);
            else if (_sCommand == ".google")
                sReply = ProcessChatGoogle(_parameters, _ip);
            else if (_sCommand == ".googleimage")
                sReply = ProcessChatGoogleImage(_parameters, _ip);
            else
                throw new NotImplementedException();

            Client.LocalUser.SendMessage(Concilium.GetDefaultReplyTarget(_sSource, _sTarget), sReply);
        }

        private dynamic SearchGoolgeFor(string _sQuery, string _sType, string _ip)
        {
            var wc = Concilium.CreateWebClient();
            _ip = _ip == null ? "" : "&userip=" + _ip;
            var result = wc.DownloadData("http://ajax.googleapis.com/ajax/services/search/" + _sType + "?v=1.0&q=" + HttpUtility.UrlEncode(_sQuery) + _ip);

            return JsonConvert.DeserializeObject(Encoding.UTF8.GetString(result));
        }

        private string ProcessChatGoogle(IList<string> _parameters, string _ip)
        {
            var query = string.Join(" ", _parameters);
            dynamic json = SearchGoolgeFor(query, "web", _ip);

            if (json.responseData == null)
            {
                Log.Get().Info(string.Format("Google search failed: {0}", json.responseDetails.Value as string));
                return string.Format("Google search failed: {0}", json.responseDetails.Value as string);
            }
            else
            {
                if (json.responseData.results == null || (json.responseData.results is JArray && (json.responseData.results as JArray).Count == 0))
                {
                    return "No results found";
                }
                else
                {
                    string url = json.responseData.results[0].url.Value;
                    string title = json.responseData.results[0].title.Value;
                    title = HttpUtility.HtmlDecode(title);

                    return string.Format("{0} {1}", title, url);
                }
            }
        }

        private string ProcessChatGoogleImage(IList<string> _parameters, string _ip)
        {
            var query = string.Join(" ", _parameters);
            var json = SearchGoolgeFor(query, "images", _ip);

            if (json.responseData == null)
            {
                Log.Get().Info(string.Format("Google search failed: {0}", json.responseDetails.Value as string));
                return string.Format("Google search failed: {0}", json.responseDetails.Value as string);
            }
            else
            {
                if (json.responseData.results == null || (json.responseData.results is JArray && (json.responseData.results as JArray).Count == 0))
                {
                    return "No results found";
                }
                else
                {
                    string url = json.responseData.results[0].url.Value;
                    string title = json.responseData.results[0].title.Value;
                    title = HttpUtility.HtmlDecode(title);

                    return string.Format("{0} {1}", title, url);
                }
            }
        }

        private string ProcessChatGoogleFight(IList<string> _parameters, string _ip)
        {
            var joinedParams = string.Join(" ", _parameters.ToArray());
            if (_parameters.Count() != 2)
                throw new InvalidCommandParametersException(".googlefight", 2);

            var json1 = SearchGoolgeFor(_parameters[0], "web", _ip);
            var json2 = SearchGoolgeFor(_parameters[1], "web", _ip);

            if (json1.responseData == null || json2.responseData == null)
            {
                Log.Get().Info(string.Format("Googlefighting failed: {0} {1}", json1.responseDetails.Value as string, json2.responseDetails.Value as string));
                return string.Format("Googlefighting failed: {0} {1}", json1.responseDetails.Value as string, json2.responseDetails.Value as string);
            }
            else
            {
                //Count and display the hits
                var hits1 = int.Parse(json1.responseData.cursor.estimatedResultCount == null ? "0" : json1.responseData.cursor.estimatedResultCount.Value as string);
                var hits2 = int.Parse(json2.responseData.cursor.estimatedResultCount == null ? "0" : json2.responseData.cursor.estimatedResultCount.Value as string);

                var total = hits1 + hits2;
                float percent1 = (float)Math.Floor(10000.0f * (float)hits1 / (float)total) / 100.0f;
                float percent2 = (float)Math.Floor(10000.0f * (float)hits2 / (float)total) / 100.0f;

                var hits1s = json1.responseData.cursor.resultCount == null ? "0" : json1.responseData.cursor.resultCount.Value as string;
                var hits2s = json2.responseData.cursor.resultCount == null ? "0" : json2.responseData.cursor.resultCount.Value as string;

                Log.Get().Info(string.Format("Googlefighting {0} and {1}", _parameters[0], _parameters[1]));
                return string.Format("\"{0}\": {1} hits ({2}%), \"{3}\": {4} hits ({5}%)", _parameters[0], hits1s, percent1, _parameters[1], hits2s, percent2);
            }
        }
    }
}
