#!/usr/bin/env python3

# http://inamidst.com/saxo/
# Created by Sean B. Palmer

import json
import re

import saxo

tag = re.compile(r"(?ims)<[^>]+>")
h2 = re.compile(r'(?ims)section id="(pod[^"]+)".*?<h2>(.*?)</h2>')
pod = re.compile(r'(?ims)popups\.(pod[^ .]+)\..*?"stringified"[^"]+' +
                 r'"([^"\\]*(?:\\.[^"\\]*)*)"')

def plain(hyper):
    text = tag.sub("", hyper)
    return normalise(text)

def normalise(text):
    text = text.replace("\t", "")
    text = text.replace("\r", "")
    text = text.replace("\n", " ")
    return text.strip()

def pretty(text):
    text = text.replace("\t", "")
    text = text.replace("\r", "")
    text = text.replace("\n", ", ")
    while "  " in text:
        text = text.replace("  ", " ")
    text = text.replace(" | ", ": ")
    return text.strip()

# TODO: Generic code
def snug(parts, limit):
    i = 0
    length = 0
    for i, text in enumerate(parts):
        length += len(text)
        if length > limit:
            break
    return parts[:i + 1]

@saxo.pipe
def c(arg):
    if arg.startswith(":long "):
        arg = arg[6:]
        limit = 256
    else:
        limit = 128

    page = saxo.request("http://www.wolframalpha.com/input/",
                        query={"asynchronous": "false", "i": arg})
    text = page["text"]

    labels = {}
    for (pod_id, label) in h2.findall(text):
        label = plain(label)
        labels[pod_id] = label.rstrip(":")

    pods = {}
    for (pod_id, string) in pod.findall(text):
        try: string = json.loads('"%s"' % string)
        except ValueError:
            string = string.replace("\\", "")
        label = labels.get(pod_id, "-")
        string = pretty(string)
        pods.setdefault(label, []).append(string)

    for (pod_id, strings) in pods.items():
        pods[pod_id] = ", ".join(strings)

    prefix = ""
    if limit > 128:
        if "Input" in pods:
            prefix = pods["Input"] + " = "
        elif "Input interpretation" in pods:
            prefix = pods["Input interpretation"] + " = "

    result = []
    # Special Case 1: The Weather
    for pod_id in pods:
        if pod_id.startswith("Latest recorded weather"):
            result.append(pods[pod_id])

    # Special Case 2: Unicode Characters
    if ("Name" in pods) and ("Encodings" in pods):
        result.append(pods["Name"])
        result.append(pods["Encodings"])

    # General Cases
    acceptable = ["Result", "Results", "Exact result",
                  "Values", "Decimal approximation"]
    for acceptable in acceptable:
        if acceptable in pods:
            result.append(pods[acceptable])

    if not result:
        # https://stackoverflow.com/questions/16868457
        for pod_id in sorted(pods, key=lambda p: len(pods[p])):
            if pod_id not in acceptable:
                result.append(pods[pod_id])

    result = [item for item in result if item]
    result = snug(result, limit)
    if result:
        return prefix + "; ".join(result)
    else:
        return "Sorry, no results"
