from contextlib import contextmanager
import xbmcgui

VIDEO_CODECS = {
    "x264": "h264",
    "h264": "h264",
    "xvid": "xvid",
}

AUDIO_CODECS = {
    "mp3": "mp3",
    "aac": "aac",
    "dts": "dts",
    "ac3": "ac3",
    "5.1ch": "ac3",
    "dd5.1ch": "ac3",
}

RESOLUTIONS = {
    # "dvdscr": (853, 480),
    # "dvdrip": (853, 480),
    "480p": (853, 480),
    "720p": (1280, 720),
    "1080p": (1920, 1080)
}


def memoize(f):
    """ Memoization decorator for a function taking one or more arguments. """
    class memodict(dict):
        def __getitem__(self, *key):
            return dict.__getitem__(self, key)

        def __missing__(self, key):
            ret = self[key] = f(*key)
            return ret

    return memodict().__getitem__


def first(iterable, default=None):
    if iterable:
        for item in iterable:
            return item
    return default


@contextmanager
def joining(thing, timeout=5):
    try:
        yield thing
    finally:
        thing.close()
        thing.join()


@contextmanager
def terminating(thing, timeout=5):
    try:
        yield thing
    finally:
        thing.close()
        thing.terminate()
        thing.join()


def get_show_info_from_name(name):
    import re
    # for r in (r"([\w\s\.\-]+)[\s\.]+S(\d+)E(\d+).*-(\w+)", r"([\w\s\.\-]+)[\s\.]+(\d+)x(\d+).*-(\w+)"):
    for r in (r"([\w\s\.\-]+)[\s\.]+S(\d+)E(\d+)", r"([\w\s\.\-]+)[\s\.]+(\d+)x(\d+)"):
        serie_result = re.search(r, name)
        if serie_result:
            return {
                "type": "serie",
                "show": serie_result.group(1),
                "season": int(serie_result.group(2)),
                "episode": int(serie_result.group(3)),
            }
    anime_result = re.search(r"\[([\w\s\.\-]+)\][\s\.]+([\w\-\s\.]+)[\s\.]+-[\s\.]+(\d+)", name)
    if anime_result:
        return {
            "type": "anime",
            "show": anime_result.group(2),
            "season": None,
            "episode": int(anime_result.group(3)),
            "group": anime_result.group(1),
        }


def get_quality_from_name(name):
    name = name.lower()
    video = {}
    audio = {}
    for codec_tag, codec_name in VIDEO_CODECS.items():
        if codec_tag in name:
            video["codec"] = codec_name
    for codec_tag, codec in AUDIO_CODECS.items():
        if codec_tag in name:
            audio["codec"] = codec_name
    for resname, res in RESOLUTIONS.items():
        if resname in name:
            video["width"], video["height"] = res
    # if we haven't found a resolution, chances are it's 480p
    if not video.get("width") and not video.get("height"):
        video["width"] = 853
        video["height"] = 480
    if video.get("width") and video.get("height"):
        video["aspect"] = float(video["width"]) / float(video["height"])
    return {
        "video": video,
        "audio": audio,
    }


def normalize_release_tags(name, real_title):
    import re
    import xbmc
    def _normalize_name(val):
        proper = re.sub(r"[\[\(\]\)]", "", val)
        proper = re.sub(r"'", "", proper)
        proper = re.sub(r"\W", " ", proper)
        proper = re.sub(r"\s+", " ", proper)
        return proper
    name = _normalize_name(name)
    real_title = _normalize_name(real_title)
    release_tags = re.compile(real_title, re.IGNORECASE).sub("", name)
    tags = map(re.escape, VIDEO_CODECS.keys() + AUDIO_CODECS.keys() + RESOLUTIONS.keys())
    release_tags = re.compile("(%s)" % "|".join(tags), re.IGNORECASE).sub("", release_tags)
    release_tags = re.sub(r"\s+", " ", release_tags)
    return release_tags.strip()


def url_get(url, params={}, headers={}, with_immunicity=True):
    import urllib2
    from contextlib import closing
    from xbmctorrentV2 import plugin
    from xbmctorrentV2.common import USER_AGENT

    if params:
        import urllib
        url = "%s?%s" % (url, urllib.urlencode(params))

    req = urllib2.Request(url)
    req.add_header("User-Agent", USER_AGENT)
    for k, v in headers.items():
        req.add_header(k, v)

    if with_immunicity and plugin.get_setting("immunicity", bool):
        from xbmctorrentV2 import immunicity
        proxy = immunicity.get_proxy_for(url)
        if proxy:
            from urlparse import urlsplit
            parts = urlsplit(url)
            req.set_proxy(proxy, parts[0])

    try:
        with closing(urllib2.urlopen(req)) as response:
            data = response.read()
            if response.headers.get("Content-Encoding", "") == "gzip":
                import zlib
                return zlib.decompressobj(16 + zlib.MAX_WBITS).decompress(data)
            return data
    except urllib2.HTTPError:
        return None

def ensure_fanart(fn):
    """Makes sure that if the listitem doesn't have a fanart, we properly set one."""
    from functools import wraps
    @wraps(fn)
    def _fn(*a, **kwds):
        import os
        import types
        from xbmctorrentV2 import plugin
        items = fn(*a, **kwds)
        if items is None:
            return
        if isinstance(items, types.GeneratorType):
            items = list(items)
        for item in items:
            properties = item.setdefault("properties", {})
            if not properties.get("fanart_image"):
                properties["fanart_image"] = plugin.addon.getAddonInfo("fanart")
        return items
    return _fn


def url_get_json(*args, **kwargs):
    import json
    data = url_get(*args, **kwargs)
    return data and json.loads(data) or {}


# Sometimes, when we do things too fast for XBMC, it doesn't like it.
# Sometimes, it REALLY doesn't like it.
# This class is here to make sure we are slow enough.
class SafeDialogProgress(xbmcgui.DialogProgress):
    def __init__(self, delay_create=1000, delay_close=1000):
        self._delay_create = delay_create
        self._delay_close = delay_close

    def create(self, *args, **kwargs):
        import xbmc
        xbmc.sleep(self._delay_create)
        super(SafeDialogProgress, self).create(*args, **kwargs)

    def close(self, *args, **kwargs):
        import xbmc
        xbmc.sleep(self._delay_close)
        super(SafeDialogProgress, self).close(*args, **kwargs)


def get_mount_filesystem(mount_point):
    from subprocess import Popen, PIPE
    for line in Popen(["/system/bin/mount"], stdout=PIPE).stdout:
        dev, mp, fs, opts, _, _ = line.split(" ")
        if mount_point == mp:
            return fs


def get_mount_point(path):
    import os
    path = os.path.realpath(os.path.abspath(path))
    while path != os.path.sep:
        if os.path.ismount(path):
            return path
        path = os.path.abspath(os.path.join(path, os.pardir))
    return path


def get_path_fs(path):
    return get_mount_filesystem(get_mount_point(path))


def get_xbmc_language():
    import xbmc
    langs = {
        "english": "en",
        "french": "fr",
    }
    return langs.get(xbmc.getLanguage().lower())

def get_api_language():
	import xbmc
	import xbmcaddon
	lang = xbmcaddon.Addon().getSetting('pref_language')
	if lang == "system": lang = xbmc.getLanguage(xbmc.ISO_639_1)
	else: lang = xbmcaddon.Addon().getSetting('pref_language')
	return lang