from . import command
import difflib
import sys
import time
import re
import collections
from lxml import etree
import logging
import requests

import .wa_parser as parser

config = None

logger = logging.getLogger('wolfram')

results = ["Result", "Response", "Infinite sum", "Decimal approximation", "Decimal form", "Limit", "Definition", "Definitions", "Description", "Balanced equation", "Chemical names and formulas", "Conversions to other units", "Roots", "Root", "Definite integral", "Plot", "Plots"]
input_categories = ["Input interpretation", "Input"]

def breakdown(data, width):
    """
    Uses heuristics to guess the data type of a piece of data, then generates an appropriate representation.
    Parses meta, lists, numbers, URLs, numbered lists and tables.
    Truncates long or multiple lines.
    """

    data = parser.delete_blank(data)
    data = parser.transpose_prepare(data)
    data = parser.replace_encoded_chars(data)
    data = parser.replace_symbol_words(data)
    data = parser.parse_maths(data)
    data = parser.parse_supersubs(data)
    data = parser.parse_all_sqrts(data)
    data = parser.shorten_urls(data)
    data = parser.rechunk(data)
    data = parser.format(data)

    return data

def query_wa(query):
    params = {"appid": config['key'], "input": query, "scantimeout": 45}

    response = requests.get("https://api.wolframalpha.com/v2/query", params=params, timeout=45)
    response = etree.fromstring(response.content)
    data = {}
    for pod in response.findall("pod"):
        title = pod.get("title")
        data[title] = "\n".join([i.findtext('plaintext') or i.find('img').get('src') for i in pod.findall('subpod')])
        if not data[title].strip():
            del data['title']

    return data

@command('wa (.+)', pass_groups=True)
def wa(bea, bot, update, groups):
    query = groups[0]
    try:
        answer = query_wa(query)
    except requests.ConnectionError as e:
        return bea.reply(f"WA error: {e}")

    if not answer:
        return bea.reply("Wolfram|Alpha returned no results for that query.")

    for i in self.input_categories:
        if i in answer:
            header = answer[i]
            remove = i
            break
    else: 
        header = f"'{query}'"
        remove = False
    
    header = " ".join(header.split())
    
    h_max = h_max or self.h_max
    
    if not category:
        results = answer
        if remove:
            results = collections.OrderedDict([(k, v) for k, v in answer.items() if k != remove])
        
        if category is not None:
            # Guess the category
            for i in self.results:
                if i in answer:
                    results = {i: results[i]}
                    break
            else:
                results = {list(results.keys())[0]: list(results.values())[0]}
    else:
        results = max(answer, key=lambda x:difflib.SequenceMatcher(None, category, x).ratio())
        results = {results:answer[results]}
    
    output = ["WA"]
    t_max = len(output[0])
    
    results = collections.OrderedDict([(k, breakdown(v.split("\n"), t_max - 3)) for k, v in results.items()])
    
    total_lines = sum([min(len(results[x]), h_max) for x in results])
    
    if total_lines > self.t_lines:
        # Too many lines, print the available categories instead.
        for i in justifiedtable(sorted(results.keys(), key=len) + ["Categories"], t_max-3):
            output.append("⎪ %s" % i)
        output[-1] = "⎩" + output[-1][5:]
    elif results:
        if len(results) == 1 and len(list(results.values())[0]) == 1:
            # Single line: Shorten output
            catname = list(results.keys())[0]
            if catname in self.results:
                output = [" │ %s " % list(results.values())[0][0]]
            else:
                output = [spacepad(" │ %s " % list(results.values())[0][0], "%s" % catname, self.t_max)]
        else:
            for category in results:
                lines = [x.rstrip() for x in results[category]]

                output.append(spacepad(" ⎨ %s " % lines.pop(0), " %s" % category, t_max))
                truncated = lines[:h_max]
                for line in truncated:
                    output.append(" ⎪ " + line)

                if len(truncated) < len(lines):
                    omission = "%d more lines" % (len(lines) - h_max + 1)
                    length = t_max - len(omission) - 6 - len(url)
                    output[-1] = " ✁ " + url + " " + ("-"*int(length)) + " %s" % omission
    else:
        output.append("No plaintext results. See <a href='http://www.wolframalpha.com/input/?i=%s'>query</a> online." % urllib.parse.quote_plus(query))))
    return bea.reply("\n".join(i.rstrip() for i in output), parse_mode='HTML')




def init(bea, _config):
    global config
    config = _config
    return [wa]
