import urllib2
from urllib import urlencode
from pulsar.util import notify
from pulsar.logger import log
from pulsar.addon import ADDON
from cookielib import CookieJar


RESOLUTION_UNKNOWN = 0
RESOLUTION_480P = 1
RESOLUTION_720P = 2
RESOLUTION_1080P = 3
RESOLUTION_1440P = 4
RESOLUTION_4K2K = 5

RIP_UNKNOWN = 0
RIP_CAM = 1
RIP_TS = 2
RIP_TC = 3
RIP_SCR = 4
RIP_DVDSCR = 5
RIP_DVD = 6
RIP_HDTV = 7
RIP_WEB = 8
RIP_BLURAY = 9

RATING_UNKNOWN = 0
RATING_PROPER = 1
RATING_NUKED = 2

CODEC_UNKNOWN = 0
CODEC_XVID = 1
CODEC_H264 = 2
CODEC_MP3 = 3
CODEC_AAC = 4
CODEC_AC3 = 5
CODEC_DTS = 6
CODEC_DTSHD = 7
CODEC_DTSHDMA = 8

USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.66 Safari/537.36"

COOKIE_JAR = CookieJar()
urllib2.install_opener(urllib2.build_opener(urllib2.HTTPCookieProcessor(COOKIE_JAR)))


class closing(object):
    def __init__(self, thing):
        self.thing = thing

    def __enter__(self):
        return self.thing

    def __exit__(self, *exc_info):
        self.thing.close()


def parse_json(data):
    try:
        import simplejson as json
    except ImportError:
        import json
    return json.loads(data)


def parse_xml(data):
    import xml.etree.ElementTree as ET
    return ET.fromstring(data)


def request(url, params={}, headers={}, data=None, method=None):
    if params:
        url = "".join([url, "?", urlencode(params)])

    req = urllib2.Request(url)
    if method:
        req.get_method = lambda: method
    req.add_header("User-Agent", USER_AGENT)
    req.add_header("Accept-Encoding", "gzip")
    for k, v in headers.items():
        req.add_header(k, v)
    if data:
        req.add_data(data)
    try:
        with closing(urllib2.urlopen(req)) as response:
            data = response.read()
            if response.headers.get("Content-Encoding", "") == "gzip":
                import zlib
                data = zlib.decompressobj(16 + zlib.MAX_WBITS).decompress(data)
            response.data = data
            response.json = lambda: parse_json(data)
            response.xml = lambda: parse_xml(data)
            return response
    except urllib2.HTTPError, e:
        log.error("http error: %s => %s" % (url, e))
        return None, None

HEAD = lambda *args, **kwargs: request(*args, method="HEAD", **kwargs)
GET = lambda *args, **kwargs: request(*args, method="GET", **kwargs)
POST = lambda *args, **kwargs: request(*args, method="POST", **kwargs)
PUT = lambda *args, **kwargs: request(*args, method="PUT", **kwargs)
DELETE = lambda *args, **kwargs: request(*args, method="DELETE", **kwargs)


def append_headers(uri, headers):
    return uri + "|" + "|".join(["%s=%s" % h for h in headers.items()])


def with_cookies(uri):
    return uri + "|Cookies=" + "; ".join(["%s=%s" % (c.name, c.value) for c in COOKIE_JAR])


def extract_magnets(data):
    import re
    for magnet in re.findall(r'magnet:\?[^\'"\s<>\[\]]+', data):
        yield {"uri": magnet}


def parse_rss(root):
    NSMAP = {
        "torrent": "http://xmlns.ezrss.it/0.1/",
        "showrss": "http://showrss.info/",
    }

    def _maybe_int(val):
        try:
            return int(val)
        except:
            return 0

    def _text(node, path):
        n = node.find(path)
        if n is not None:
            return n.text

    def _attr(node, path, attrib):
        n = node.find(path)
        if n is not None:
            return n.attrib.get(attrib)

    for item in root.getiterator("item"):
        yield {
            "name": _text(item, "title") or _text(item, ".//{%(torrent)s}fileName" % NSMAP) or _text(item, ".//{%(showrss)s}rawtitle" % NSMAP),
            "info_hash": _text(item, ".//info_hash") or _text(item, ".//{%(showrss)s}info_hash" % NSMAP),
            "uri": _text(item, ".//{%(torrent)s}magnetURI" % NSMAP) or _attr(item, ".//enclosure", "url") or _text(item, "./link"),
            "seeds": _maybe_int(_text(item, ".//{%(torrent)s}seeds" % NSMAP) or _text(item, "numSeeders") or _text(item, "seeders")),
            "peers": _maybe_int(_text(item, ".//{%(torrent)s}peers" % NSMAP) or _text(item, "numLeechers") or _text(item, "leechers")),
            "size": _maybe_int(_text(item, ".//{%(torrent)s}contentLength" % NSMAP) or _attr(item, ".//enclosure", "length")),
        }


# Borrowed from xbmcswift2
def get_setting(key, converter=str, choices=None):
    value = ADDON.getSetting(id=key)
    if converter is str:
        return value
    elif converter is unicode:
        return value.decode('utf-8')
    elif converter is bool:
        return value == 'true'
    elif converter is int:
        return int(value)
    elif isinstance(choices, (list, tuple)):
        return choices[int(value)]
    else:
        raise TypeError('Acceptable converters are str, unicode, bool and '
                        'int. Acceptable choices are instances of list '
                        ' or tuple.')


def set_setting(key, val):
    return ADDON.setSetting(id=key, value=val)


def register(search, search_movie, search_episode):
    import base64
    import json
    import sys

    try:
        payload = json.loads(base64.b64decode(sys.argv[1]))
    except:
        notify(ADDON.getLocalizedString(30102).encode('utf-8'), time=1000)
        return

    results = ()
    method = {
        "search": search,
        "search_movie": search_movie,
        "search_episode": search_episode,
    }.get(payload["method"]) or (lambda *a, **kw: [])
    try:
        results = ()
        objects = method(payload["search_object"])
        if objects is not None:
            results = tuple(objects)
    finally:
        urllib2.urlopen(
            payload["callback_url"],
            data=json.dumps(results)
        )
