from os import path
from kodipopcorntime import plugin
from kodipopcorntime.caching import cached_route
from kodipopcorntime.utils import ensure_fanart
from kodipopcorntime.library import library_context
from kodipopcorntime.magnet import from_meta_data
import xbmcaddon

BASE_URL = "%s/" % plugin.get_setting("base_yify")
HEADERS = {
    "Referer": BASE_URL,
}
MOVIES_PER_PAGE = 20
GENRES = [
    "Action",
    "Adventure",
    "Animation",
    "Biography",
    "Comedy",
    "Crime",
    "Documentary",
    "Drama",
    "Family",
    "Fantasy",
    "Film-Noir",
    "Game-Show",
    "History",
    "Horror",
    "Music",
    "Musical",
    "Mystery",
    "News",
    "Reality-TV",
    "Romance",
    "Sci-Fi",
    "Sport",
    "Talk-Show",
    "Thriller",
    "War",
    "Western",
]
# Cache TTLs
DEFAULT_TTL = 24 * 3600 # 24 hours

def index():
    return [
        {
            "label": "Search",
            "icon": path.join(plugin.addon.getAddonInfo('path'), 'resources', 'icons', 'Search.png'),
            "thumbnail": path.join(plugin.addon.getAddonInfo('path'), 'resources', 'icons', 'Search.png'),
            "path": plugin.url_for("search")
        },
        {
            "label": "Browse by Genre",
            "icon": path.join(plugin.addon.getAddonInfo('path'), 'resources', 'icons', 'Genres.png'),
            "thumbnail": path.join(plugin.addon.getAddonInfo('path'), 'resources', 'icons', 'Genres.png'),
            "path": plugin.url_for("genres")
        },
        {
            "label": "Most Popular",
            "icon": path.join(plugin.addon.getAddonInfo('path'), 'resources', 'icons', 'Top.png'),
            "thumbnail": path.join(plugin.addon.getAddonInfo('path'), 'resources', 'icons', 'Top.png'),
            "path": plugin.url_for("movies", sort_by="seeds", order="desc", quality="all", page=1, limit=MOVIES_PER_PAGE)
        },
        {
            "label": "Best Rated",
            "icon": path.join(plugin.addon.getAddonInfo('path'), 'resources', 'icons', 'Top.png'),
            "thumbnail": path.join(plugin.addon.getAddonInfo('path'), 'resources', 'icons', 'Top.png'),
            "path": plugin.url_for("movies", sort_by="rating", order="desc", quality="all", page=1, limit=MOVIES_PER_PAGE)
        },
        {
            "label": "Most Recent",
            "icon": path.join(plugin.addon.getAddonInfo('path'), 'resources', 'icons', 'Recently.png'),
            "thumbnail": path.join(plugin.addon.getAddonInfo('path'), 'resources', 'icons', 'Recently.png'),
            "path": plugin.url_for("movies", sort_by="date", order="desc", quality="all", page=1, limit=MOVIES_PER_PAGE)
        },
    ]

@library_context
def show_data(callback):
    import xbmc
    import xbmcgui
    from contextlib import nested, closing
    from itertools import izip, chain
    from concurrent import futures
    from kodipopcorntime.scrapers import tmdb, yifysubs
    from kodipopcorntime.utils import url_get_json, SafeDialogProgress

    plugin.set_content("movies")
    args = dict((k, v[0]) for k, v in plugin.request.args.items())

    current_page = int(args["page"])
    limit = int(args["limit"])

    with closing(SafeDialogProgress(delay_close=0)) as dialog:
        dialog.create(plugin.name)
        dialog.update(percent=0, line1="Fetching movie information...", line2="", line3="")

        try:
            search_result = url_get_json("%s/api/v2/list_movies.json" % BASE_URL, params=args, headers=HEADERS)
        except:
            plugin.notify("Unable to connect to %s." % BASE_URL)
            raise
        movies = search_result.get("data").get("movies") or []
        movie_count = int(search_result.get("data")["movie_count"])

        if not movies:
            return

        state = {"done": 0}
        def on_movie(future):
            data = future.result()
            state["done"] += 1
            dialog.update(
                percent=int(state["done"] * 100.0 / len(movies)),
                line2=data.get("title") or data.get("MovieTitleClean") or "",
            )

        with futures.ThreadPoolExecutor(max_workers=2) as pool_tmdb:
            tmdb_list = [pool_tmdb.submit(tmdb.get, movie["imdb_code"]) for movie in movies]
            [future.add_done_callback(on_movie) for future in tmdb_list]
            while not all(job.done() for job in tmdb_list):
                if dialog.iscanceled():
                    return
                xbmc.sleep(100)

        tmdb_list = map(lambda job: job.result(), tmdb_list)
        for movie, tmdb_meta in izip(movies, tmdb_list):
            if tmdb_meta:
                sub = yifysubs.get_sub_items(movie["imdb_code"])
                if sub == None:
                    sub = ["none", ""]

                for torrent in movie["torrents"]:
                    item = tmdb.get_list_item(tmdb_meta)

                    if args.get("quality") == "all" and torrent["quality"] != "720p":
                        item["label"] = "%s (%s)" % (item["label"], torrent["quality"])

                    if item.get("info").get("duration") == 0:
                        item["info"]["duration"] = movie["runtime"]

                    item.update({
                        "path": plugin.url_for("play", sub=sub[0], uri=from_meta_data(torrent["hash"], movie["title_long"], torrent["quality"])),
                        "is_playable": True,
                    })

                    item.setdefault("info", {}).update({
                        "code": movie["imdb_code"],
                        "size": torrent["size_bytes"],
                    })

                    width = 1920
                    height = 1080
                    if torrent["quality"] == "720p":
                        width = 1280
                        height = 720
                    item.setdefault("stream_info", {}).update({
                        "video": {
                            "codec": "h264",
                            "width": width,
                            "height": height,
                        },
                        "audio": {
                            "codec": "aac",
                            "language": "en",
                        },
                        "subtitle": {
                            "language": sub[1],
                        },
                    })

                    yield item

        if current_page < (movie_count / limit):
            next_args = args.copy()
            next_args["page"] = int(next_args["page"]) + 1
            yield {
                "label": ">> Next page",
                "path": plugin.url_for(callback, **next_args),
            }

@plugin.route("/genres")
@ensure_fanart
def genres():
    for genre in GENRES:
        yield {
            "label": genre,
            "path": plugin.url_for("genre", genre=genre, sort_by="seeds", order="desc", quality="all", page=1, limit=MOVIES_PER_PAGE),
        }

@plugin.route("/genres/<genre>/<page>")
@cached_route(ttl=DEFAULT_TTL, content_type="movies")
@ensure_fanart
def genre(genre, page):
    plugin.request.args.update({
        "genre": [genre],
        "page": [page],
    })
    return show_data("genre")

@plugin.route("/browse/<sort_by>/<quality>/<page>")
@cached_route(ttl=DEFAULT_TTL, content_type="movies")
@ensure_fanart
def movies(sort_by, quality, page):
    plugin.request.args.update({
        "sort_by": [sort_by],
        "quality": [quality],
        "page": [page],
    })
    return show_data("movies")

@plugin.route("/search")
def search():
    query = plugin.request.args.get("query")
    if query:
        query = query[0]
    else:
        query = plugin.keyboard("", "KODI Popcorn Time - Search")
    if query:
        plugin.redirect(plugin.url_for("search_query", query_term=query, quality="all", page=1, limit=MOVIES_PER_PAGE))

@plugin.route("/search/<query_term>/<page>")
@cached_route(ttl=DEFAULT_TTL, content_type="movies")
@ensure_fanart
def search_query(query_term, page):
    plugin.request.args.update({
        "query_term": [query_term],
        "page": [page],
    })
    return show_data("search_query")