# -*- coding: utf-8 -*-
# ------------------------------------------------------------
# smytvshow
# Various types of Items
# http://smystero.dlinkddns.org/smytvwhow/
# ------------------------------------------------------------

import urllib
import urlparse
import re

from core import common as c
from xbmcutils import config, logger  #, message

if config.use_mysql:
    from mysqlinterface import sql_manager as sql
else:
    from sql import sql_manager as sql


def url_encode(dictionary):
    return urllib.urlencode(encode_dic(dictionary))


def url_decode(query):
    out_dict = dict()
    for key, value in urlparse.parse_qs(query).iteritems():
        out_dict[key] = value[0]

    return out_dict


def encode_dic(dictionary={}):
    x = dict()
    for k, v in dictionary.items():
        if isinstance(k, str):
            u = unicode(k, 'utf-8', errors='ignore')
            k1 = u.encode('utf-8')
        else:
            k1 = k.encode('utf-8')
        if isinstance(v, str):
            try:
                u = unicode(v, 'utf-8', errors='ignore')
            except Exception, e:
                try:
                    u = unicode(v, 'ISO-8859-1')
                except:
                    u = u""
                    pass
            v1 = u.encode('utf-8')
        elif isinstance(v, unicode):
            v1 = v.encode('utf-8')
        else:
            v1 = unicode(v).encode('utf-8')
        x[k1] = v1
    return x
    # return dict([k.encode('utf-8'), unicode(v).encode('utf-8')] for k, v in dictionary.items())


def plan_dic(prefix="", dictionary={}):
    x = dict()
    for k, v in dictionary.items():
        if isinstance(k, str):
            u = unicode(k, 'utf-8')
            k1 = (prefix + '.' + u).encode('utf-8')
        else:
            k1 = (prefix + '.' + k).encode('utf-8')
        if isinstance(v, str):
            u = unicode(v, 'utf-8', errors='ignore')
            try:
                u = unicode(v, 'utf-8', errors='ignore')
            except Exception, e:
                try:
                    u = unicode(v, 'ISO-8859-1')
                except:
                    u = u""
                    pass
            v1 = u.encode('utf-8')
        elif isinstance(v, unicode):
            v1 = v.encode('utf-8')
        else:
            v1 = unicode(v).encode('utf-8')
        x[k1] = v1
    return x
    # return dict([(prefix + '.' + k).encode('utf-8'), unicode(v).encode('utf-8')] for k, v in dictionary.items())


class SafeDict(dict):
    def __init__(self):
        dict.__init__(self)

    def __getitem__(self, key):
        if key not in self:
            return ""
        else:
            return dict.__getitem__(self, key)


class CallerItem(object):
    def __init__(self, properties):
        self.item_info = SafeDict()

        self.item_info.update(properties)

    def build_url(self):
        query = dict()
        query.update(self.item_info)

        data = urllib.urlencode(encode_dic(query))
        ret = config.get_base() + '?' + data

        return ret

class BaseItem(object):
    def __init__(self, source_object, title, action, target_type="", target="", folder=True, playable=True):
        self.source_type = ""
        self.source = ""
        self.target_type = ""
        self.target = ""
        self.title = ""
        self.action = ""
        self.folder = True
        self.playable = True

        if source_object is not None:
            if hasattr(source_object, "__object_type__"):
                self.source_type = source_object.__object_type__
            if hasattr(source_object, "__object_name__"):
                self.source = source_object.__object_name__

        if target_type == "":
            self.target_type = self.source_type
        else:
            self.target_type = target_type

        if target == "":
            self.target = self.source
        else:
            self.target = target

        self.title = title
        self.action = action
        self.folder = folder
        self.playable = playable

    def infos(self):
        return dict()

    def build_url(self):
        query = dict(caller=self.__class__.__name__, source_type=self.source_type, source=self.source,
                     target_type=self.target_type, target=self.target, action=self.action)
        query.update(self.infos())

        data = urllib.urlencode(encode_dic(query))
        ret = config.get_base() + '?' + data

        return ret


class MenuItem(BaseItem):
    def __init__(self, source_object, title, action, extra={}, target_type="", target="", folder=True, playable=True,
                 thumbnail="", poster="", fanart="", banner=""):
        self.extra = {}
        if fanart == "":
            fanart = "[fanart]"

        if thumbnail.startswith("[") and thumbnail.endswith("]"):
            import os
            thumbnail = os.path.join(config.get_plugin_path(), "resources", "media", thumbnail[1:-1] + ".png")

        if poster.startswith("[") and poster.endswith("]"):
            import os
            poster= os.path.join(config.get_plugin_path(), "resources", "media", poster[1:-1] + ".png")

        if fanart.startswith("[") and fanart.endswith("]"):
            import os
            fanart = os.path.join(config.get_plugin_path(), "resources", "media", fanart[1:-1] + ".png")

        if banner.startswith("[") and banner.endswith("]"):
            import os
            banner = os.path.join(config.get_plugin_path(), "resources", "media", banner[1:-1] + ".png")

        self.thumbnail = thumbnail
        self.poster = poster
        self.fanart = fanart
        self.banner = banner

        BaseItem.__init__(self, source_object, title, action, target_type, target, folder, playable)

        self.extra = extra

    def infos(self):
        data = BaseItem.infos(self)

        if self.extra is not None:
            data.update(plan_dic("extra", self.extra))

        return data


class VideoItem(BaseItem):
    def __init__(self, source_object, caller_item, title, action, extra={}, target_type="", target="", folder=True,
                 playable=True):
        self.properties = {}
        self.extra = {}
        self.caller_item = caller_item

        BaseItem.__init__(self, source_object, title, action, target_type, target, folder, playable)

        self.init_properties(caller_item)
        self.extra = extra

    def init_properties(self, item):
        self.properties.update(dict())

        if isinstance(item, CallerItem):
            if item.item_info["caller"] in (
                    "VideoItem", "ShowItem", "SeasonItem", "EpisodeItem", "ServerItem", "MediaItem"):
                self.properties.update(dict())

        return

    def infos(self):
        data = BaseItem.infos(self)

        if self.extra is not None:
            data.update(plan_dic("extra", self.extra))

        return data


class ShowItem(VideoItem):
    def __init__(self, source_object, caller_item, show_id, title, action, extra={}, target_type="", target="",
                 folder=True,
                 playable=True):

        self.show_id = show_id
        VideoItem.__init__(self, source_object, caller_item, title, action, extra, target_type, target, folder,
                           playable)

        if self.show_id == 0:
            import hashlib

            m = hashlib.md5()
            m.update(title)
            digest = m.hexdigest()

            s = sql.SqlManager()
            data = s.find_show_by_pusher_digest(self.source, digest)
            del s

            if data is not None:
                self.show_id = data[0]

        if self.show_id != 0:

            s = sql.SqlManager()
            data = s.get_original_title(self.show_id)
            del s

            from tvdb import tvdb_api
            tv_db = tvdb_api.TvDb()
            tv_show = tv_db[self.show_id]

            if data is not None:
                tv_show["originalseriesname"] = data[0]

            self.decorate(tv_show)

    def init_properties(self, item):
        VideoItem.init_properties(self, item)
        self.properties.update(
            genre="",  # split with /
            year=0,
            rating=0.0,
            cast=[],
            castandrole=[],
            mpaa="",
            plot="",
            plotoutline="",
            duration="60",
            originaltitle="",
            tvshowtitle="",
            title="",
            premiered="",
            status="",
            code="",
            votes="",
            dateadded="",
            fanart="",
            poster="",
            banner="")

        if isinstance(item, CallerItem):
            if item.item_info["caller"] in ("ShowItem", "SeasonItem", "EpisodeItem", "ServerItem", "MediaItem"):
                import ast

                self.properties.update(
                    genre=item.item_info["genre"],
                    year=int(item.item_info["year"]),
                    rating=float(item.item_info["rating"]),
                    cast=ast.literal_eval(item.item_info["cast"]),
                    castandrole=ast.literal_eval(item.item_info["castandrole"]),
                    mpaa=item.item_info["mpaa"],
                    plot=item.item_info["plot"],
                    plotoutline=item.item_info["plotoutline"],
                    duration=item.item_info["duration"],
                    originaltitle=item.item_info["originaltitle"],
                    tvshowtitle=item.item_info["tvshowtitle"],
                    title=item.item_info["title"],
                    premiered=item.item_info["premiered"],
                    status=item.item_info["status"],
                    code=item.item_info["code"],
                    votes=item.item_info["votes"],
                    dateadded=item.item_info["dateadded"],
                    fanart=item.item_info["fanart"],
                    poster=item.item_info["poster"],
                    banner=item.item_info["banner"])
        return

    def decorate(self, tv_show):
        try:

            self.properties["genre"] = c.pipe_split(tv_show["genre"])

            premiered = tv_show["firstaired"]
            if premiered is not None:
                self.properties["year"] = premiered[:4]

            # year = 0
            self.properties["rating"] = float(get_value(tv_show, "rating", "0.0"))

            self.properties["cast"] = []
            patron = '\|([^\|]+)'
            actors = re.compile(patron, re.DOTALL).findall(tv_show['actors'])
            for actor in actors:
                self.properties["cast"].append(actor)

            self.properties["castandrole"] = []
            try:
                actors = tv_show['_actors']
                for actor in actors:
                    self.properties["castandrole"].append((actor["name"], actor["role"]))
            except Exception, e:
                self.properties["castandrole"] = self.properties["cast"]
                pass

            self.properties["mpaa"] = tv_show["contentrating"]

            self.properties["plot"] = tv_show["overview"]
            self.properties["plotoutline"] = tv_show["overview"]

            self.properties["duration"] = str(tv_show["runtime"])

            self.properties["tvshowtitle"] = tv_show["seriesname"]
            self.properties["title"] = tv_show["seriesname"]

            try:
                if tv_show["originalseriesname"]:
                   self.properties["originaltitle"] = tv_show["originalseriesname"]
            except Exception, e:
                self.properties["originaltitle"] = tv_show["seriesname"]
                pass

            self.properties["premiered"] = premiered

            self.properties["status"] = tv_show["status"]

            self.properties["code"] = tv_show["imdb_id"]

            self.properties["votes"] = tv_show["ratingcount"]

            self.properties["dateadded"] = tv_show["added"]

            self.properties["banner"] = tv_show["banner"]
            self.properties["fanart"] = tv_show["fanart"]
            self.properties["poster"] = tv_show["poster"]
        except Exception, e:
            logger.error(e.message)

    def infos(self):
        data = VideoItem.infos(self)

        data.update(show_id=self.show_id)
        data.update(self.properties)

        return data


class SeasonItem(ShowItem):
    def __init__(self, source_object, caller_item, show_id, season, title, action, extra={}, target_type="", target="",
                 folder=True,
                 playable=True):
        self.season = season
        ShowItem.__init__(self, source_object, caller_item, show_id, title, action, extra, target_type, target, folder,
                          playable)

    def init_properties(self, item):
        ShowItem.init_properties(self, item)

        self.properties.update(season=0)
        self.properties.update(episode_count=0)
        self.properties.update(subbed=0)

        if isinstance(item, CallerItem):
            if item.item_info["caller"] in ("SeasonItem", "EpisodeItem", "ServerItem", "MediaItem"):
                self.properties.update(
                    season=int(item.item_info["season"]),
                    episode_count=int(item.item_info["episode_count"]),
                    subbed = int(item.item_info["subbed"]),
                    title=item.item_info["title"],
                    poster=item.item_info["poster"]
                )

        return

    def decorate(self, tv_show):
        ShowItem.decorate(self, tv_show)

        # populate season element using the tv_db_item[season]
        self.properties["title"] = config.get_localized_string(30901) % str(self.season)
        try:
            tv_season = tv_show[self.season]
            self.properties["season"] = self.season
            self.properties["episode_count"] = len(tv_season)
            if tv_show['_banners'] is not None:
                for btype in tv_show['_banners']:
                    if btype == "season":
                        for btype2 in tv_show['_banners'][btype]:
                            if btype2 == 'season':
                                max_rating = float("-0.1")
                                for bid in tv_show['_banners'][btype][btype2]:
                                    seas = 0
                                    lang = "xx"
                                    rating = float("0.0")
                                    for k, v in list(tv_show['_banners'][btype][btype2][bid].items()):
                                        if k == "rating":
                                            try:
                                                rating = float(v)
                                            except:
                                                pass
                                        if k == "season":
                                            try:
                                                seas = int(v)
                                            except:
                                                pass
                                        if k == "language":
                                            try:
                                                lang = v
                                            except:
                                                pass
                                    if (seas == self.season) \
                                            and (lang == config.language or lang == "en") \
                                            and (rating > max_rating):
                                        self.properties["poster"] = tv_show['_banners'][btype][btype2][bid][
                                            "_bannerpath"]
                                        max_rating = rating
        except Exception, e:
            logger.error(e.message)
            pass

    def infos(self):
        data = ShowItem.infos(self)

        data.update(item_season=self.season)
        data.update(self.properties)

        return data


class EpisodeItem(SeasonItem):
    def __init__(self, source_object, caller_item, show_id, season, episode, title, action, extra={}, target_type="",
                 target="",
                 folder=False,
                 playable=False):
        self.episode = episode
        self.from_search = False
        SeasonItem.__init__(self, source_object, caller_item, show_id, season, title, action, extra, target_type,
                            target, folder,
                            playable)

    def init_properties(self, item):
        SeasonItem.init_properties(self, item)

        self.properties.update(
            episode=0,
            director="",
            writer="",
            overlay=6,
            playcount=0)

        if isinstance(item, CallerItem):
            if item.item_info["caller"] in ("EpisodeItem", "ServerItem", "MediaItem"):
                self.properties.update(
                    episode=int(item.item_info["episode"]),
                    rating=float(get_value(item.item_info, "rating", "0.0")),
                    director=item.item_info["director"],
                    plot=item.item_info["plot"],
                    plotoutline=item.item_info["plotoutline"],
                    writer=item.item_info["writer"],
                    premiered=item.item_info["premiered"],
                    code=item.item_info["code"],
                    votes=item.item_info["votes"],
                    title=item.item_info["title"],
                    poster=item.item_info["poster"],
                    overlay=int(get_value(item.item_info, "overlay", "0")),
                    playcount=int(get_value(item.item_info, "playcount", "0"))
                )

        return

    def decorate(self, tv_show):
        SeasonItem.decorate(self, tv_show)

        # populate episode element using the tv_db_item[season][episode]
        self.properties["title"] = config.get_localized_string(30902) % str(self.episode)
        try:
            tv_episode = tv_show[self.season][self.episode]
            self.properties["episode"] = self.episode
            self.properties["rating"] = float(get_value(tv_episode, "rating", "0.0"))
            self.properties["director"] = tv_episode["director"]
            self.properties["plot"] = tv_episode["overview"]
            self.properties["plotoutline"] = tv_episode["overview"]
            self.properties["writer"] = c.pipe_split(tv_episode["writer"])
            self.properties["premiered"] = tv_episode["firstaired"]
            self.properties["code"] = tv_episode["imdb_id"]
            self.properties["votes"] = tv_episode["ratingcount"]
            self.properties["title"] = tv_episode["episodename"]
            self.properties["poster"] = tv_episode["filename"]

            s = sql.SqlManager()
            if s.get_trakt(self.show_id, int(self.season),int(self.episode)):
                self.properties["overlay"] = 7
                self.properties["playcount"] = 10
            del s

        except Exception, e:
            logger.error(e.message)
            pass

    def infos(self):
        data = SeasonItem.infos(self)

        data.update(item_episode=self.episode)
        data.update(self.properties)

        return data


class ServerItem(EpisodeItem):
    def __init__(self, source_object, caller_item, show_id, season, episode, server_id, title, action, extra={},
                 target_type="",
                 target="",
                 folder=False,
                 playable=False):
        self.server_id = server_id
        EpisodeItem.__init__(self, source_object, caller_item, show_id, season, episode, title, action, extra,
                             target_type, target, folder, playable)

    def init_properties(self, item):
        EpisodeItem.init_properties(self, item)

        self.properties.update(
            server="",
            video_id="")

        if isinstance(item, CallerItem):
            if item.item_info["caller"] in ("ServerItem", "MediaItem"):
                self.properties.update(
                    server=item.item_info["server"],
                    video_id=item.item_info["video_id"],
                    title=item.item_info["title"])

        return

    def decorate(self, tv_show):
        EpisodeItem.decorate(self, tv_show)
        self.properties["tvshowtitle"] = self.properties["originaltitle"]

    def infos(self):
        data = EpisodeItem.infos(self)

        data.update(item_server_id=self.server_id)
        data.update(self.properties)

        return data


class MediaItem(ServerItem):
    def __init__(self, source_object, caller_item, show_id, season, episode, server_id, media_url, title, action,
                 extra={},
                 target_type="",
                 target="",
                 folder=False,
                 playable=False):
        self.media_url = media_url
        ServerItem.__init__(self, source_object, caller_item, show_id, season, episode, server_id, title, action, extra,
                            target_type, target, folder, playable)

    def init_properties(self, item):
        ServerItem.init_properties(self, item)

        self.properties.update(
            path="",
            quality="")


        if isinstance(item, CallerItem):
            if item.item_info["caller"] in ("MediaItem"):
                self.properties.update(
                    path=item.item_info["path"],
                    quality=item.item_info["quality"],
                    title=item.item_info["title"])

        return

    def decorate(self, tv_show):
        ServerItem.decorate(self, tv_show)

    def infos(self):
        data = ServerItem.infos(self)

        data.update(item_media_url=self.media_url)
        data.update(self.properties)

        return data


class TestMediaItem(MenuItem):
    def __init__(self, source_object, title, action, extra={}, target_type="", target="", folder=True, playable=True,
                 thumbnail="", poster="", fanart="", banner=""):
        MenuItem.__init__(self, source_object, title, action, extra, target_type, target, folder, playable,
                          thumbnail, poster, fanart, banner)

    def build_url(self):
        #ret = "http://download.wavetlan.com/SVV/Media/HTTP/H264/Other_Media/H264_test7_voiceclip_mp4_480x360.mp4"
        ret = ""
        return ret

def get_value(dictionary, key, default):
    if key in dictionary:
        if dictionary[key] is not None:
            return dictionary[key]
        else:
            return default
    else:
        return default


