Implemented most features
Implemented most features

file:a/README.md -> file:b/README.md
--- a/README.md
+++ b/README.md
@@ -6,23 +6,25 @@
 
 Forum posting: xxx
 
-**WARNING: You MUST be a PREMIUM member OR buy videos to use this plugin!**
+**WARNING: You MUST be a PREMIUM member to use this plugin!**
 ***
 
 What this plugin currently can do:
 - [x] Supports all Crunchyroll regions
 - [x] Login with your account
-- [ ] Search for animes
-- [ ] Browse all popular anime/drama
-- [ ] Browse all simulcasts
-- [ ] Browse all updated anime/drama
-- [ ] Browse all anime/drama alphabetically
-- [ ] Browse all genres
-- [ ] Browse all seasons
+- [x] Search for animes
+- [x] Browse all featured anime/drama
+- [x] Browse all popular anime/drama
+- [x] Browse all simulcasts
+- [x] Browse all updated anime/drama
+- [x] Browse all new anime/drama
+- [x] Browse all anime/drama alphabetically
+- [x] Browse all genres
+- [x] Browse all seasons
 - [x] View queue/playlist
 - [x] View history
-- [ ] View all seasons/arcs of an anime/drama
-- [ ] View all episodes of an season/arc
+- [x] View all seasons/arcs of an anime/drama
+- [x] View all episodes of an season/arc
 - [ ] Add or remove anime/drama from your queue/playlist
 - [x] Display various informations
 - [x] Watch videos with premium subscription

--- a/resources/language/resource.language.de_de/strings.po
+++ b/resources/language/resource.language.de_de/strings.po
@@ -115,6 +115,10 @@
 msgid "Random"
 msgstr "Zufällig"
 
+msgctxt "#30044"
+msgid "Next page"
+msgstr "Nächste Seite"
+
 msgctxt "#30050"
 msgid "Anime"
 msgstr "Anime"
@@ -147,6 +151,14 @@
 msgid "Seasons"
 msgstr "Seasons"
 
+msgctxt "#30058"
+msgid "Featured"
+msgstr "Empfohlen"
+
+msgctxt "#30059"
+msgid "Newest"
+msgstr "Neuste"
+
 
 # Crunchyroll Messages
 

--- a/resources/language/resource.language.en_gb/strings.po
+++ b/resources/language/resource.language.en_gb/strings.po
@@ -115,6 +115,10 @@
 msgid "Random"
 msgstr ""
 
+msgctxt "#30044"
+msgid "Next page"
+msgstr ""
+
 msgctxt "#30050"
 msgid "Anime"
 msgstr ""
@@ -147,6 +151,14 @@
 msgid "Seasons"
 msgstr ""
 
+msgctxt "#30058"
+msgid "Featured"
+msgstr ""
+
+msgctxt "#30059"
+msgid "Newest"
+msgstr ""
+
 
 # Crunchyroll Messages
 

--- a/resources/lib/api.py
+++ b/resources/lib/api.py
@@ -50,7 +50,7 @@
     cj = LWPCookieJar()
     args._cj = cj
 
-    # lets urllib2 handle cookies
+    # lets urllib handle cookies
     opener = build_opener(HTTPCookieProcessor(cj))
     opener.addheaders = [("User-Agent",      "Mozilla/5.0 (iPhone; iPhone OS 8.3.0; en_US)"),
                          ("Accept-Encoding", "identity"),
@@ -58,7 +58,7 @@
                          ("Content-Type",    "application/x-www-form-urlencoded")]
     install_opener(opener)
 
-    # check if cookies exist
+    # load cookies
     try:
         cj.load(getCookiePath(args), ignore_discard=True)
     except IOError:

--- a/resources/lib/controller.py
+++ b/resources/lib/controller.py
@@ -16,6 +16,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import sys
+import json
 import time
 
 import xbmc
@@ -31,9 +32,9 @@
     """
     # api request
     payload = {"media_types": "anime|drama",
-               "fields":      "media.name,media.media_id,media.description,media.episode_number,media.created,media.media_type,media.screenshot_image, \
-                               media.premium_only,media.premium_available,media.available,media.premium_available,media.duration, \
-                               series.name,series.series_id,series.year,series.publisher_name,series.rating,series.portrait_image"}
+               "fields":      "media.name,media.media_id,media.collection_id,media.collection_name,media.description,media.episode_number,media.created, \
+                               media.screenshot_image,media.premium_only,media.premium_available,media.available,media.premium_available,media.duration, \
+                               series.series_id,series.year,series.publisher_name,series.rating,series.genres,series.landscape_image"}
     req = api.request(args, "queue", payload)
 
     # check for error
@@ -50,38 +51,81 @@
 
         # add to view
         view.add_item(args,
-                      {"title":       item["series"]["name"] + " #" + item["most_likely_media"]["episode_number"] + " - " + item["most_likely_media"]["name"],
-                       "tvshowtitle": item["series"]["name"],
-                       "duration":    item["most_likely_media"]["duration"],
-                       "playcount":   1 if (100/int(item["most_likely_media"]["duration"]))*int(item["playhead"]) > 90 else 0,
-                       "episode":     item["most_likely_media"]["episode_number"],
-                       "episode_id":  item["most_likely_media"]["media_id"],
-                       "series_id":   item["series"]["series_id"],
-                       "plot":        item["most_likely_media"]["description"],
-                       "plotoutline": item["most_likely_media"]["description"],
-                       "genre":       item["most_likely_media"]["media_type"],
-                       "year":        item["series"]["year"],
-                       "aired":       item["most_likely_media"]["created"][:10],
-                       "premiered":   item["most_likely_media"]["created"][:10],
-                       "studio":      item["series"]["publisher_name"],
-                       "rating":      int(item["series"]["rating"])/10.0,
-                       "thumb":       item["most_likely_media"]["screenshot_image"]["fwidestar_url"] if item["most_likely_media"]["premium_only"] else item["most_likely_media"]["screenshot_image"]["full_url"],
-                       "fanart":      item["series"]["portrait_image"]["full_url"],
-                       "mode":        "videoplay"},
+                      {"title":         item["most_likely_media"]["collection_name"] + " #" + item["most_likely_media"]["episode_number"] + " - " + item["most_likely_media"]["name"],
+                       "tvshowtitle":   item["most_likely_media"]["collection_name"],
+                       "duration":      item["most_likely_media"]["duration"],
+                       "playcount":     1 if (100/float(item["most_likely_media"]["duration"]))*int(item["playhead"]) > 90 else 0,
+                       "episode":       item["most_likely_media"]["episode_number"],
+                       "episode_id":    item["most_likely_media"]["media_id"],
+                       "collection_id": item["most_likely_media"]["collection_id"],
+                       "series_id":     item["series"]["series_id"],
+                       "plot":          item["most_likely_media"]["description"],
+                       "plotoutline":   item["most_likely_media"]["description"],
+                       "genre":         ", ".join(item["series"]["genres"]),
+                       "year":          item["series"]["year"],
+                       "aired":         item["most_likely_media"]["created"][:10],
+                       "premiered":     item["most_likely_media"]["created"][:10],
+                       "studio":        item["series"]["publisher_name"],
+                       "rating":        int(item["series"]["rating"])/10.0,
+                       "thumb":         item["most_likely_media"]["screenshot_image"]["fwidestar_url"] if item["most_likely_media"]["premium_only"] else item["most_likely_media"]["screenshot_image"]["full_url"],
+                       "fanart":        item["series"]["landscape_image"]["full_url"],
+                       "mode":          "videoplay"},
                       isFolder=False)
 
     view.endofdirectory()
     return True
 
 
+def searchAnime(args):
+    """Search for anime
+    """
+    # ask for search string
+    d = xbmcgui.Dialog().input(args._addon.getLocalizedString(30021), type=xbmcgui.INPUT_ALPHANUM)
+    if not d:
+        return
+
+    # api request
+    payload = {"media_types": "anime|drama",
+               "q":           d,
+               "fields":      "series.name,series.series_id,series.description,series.year,series.publisher_name, \
+                               series.genres,series.portrait_image,series.landscape_image"}
+    req = api.request(args, "autocomplete", payload)
+
+    # check for error
+    if req["error"]:
+        view.add_item(args, {"title": args._addon.getLocalizedString(30061)})
+        view.endofdirectory()
+        return False
+
+    # display media
+    for item in req["data"]:
+        # add to view
+        view.add_item(args,
+                      {"title":       item["name"],
+                       "tvshowtitle": item["name"],
+                       "series_id":   item["series_id"],
+                       "plot":        item["description"],
+                       "plotoutline": item["description"],
+                       "genre":       ", ".join(item["genres"]),
+                       "year":        item["year"],
+                       "studio":      item["publisher_name"],
+                       "thumb":       item["portrait_image"]["full_url"],
+                       "fanart":      item["landscape_image"]["full_url"],
+                       "mode":        "series"},
+                      isFolder=True)
+
+    view.endofdirectory()
+    return True
+
+
 def showHistory(args):
-    """ shows history of watched animes
+    """ shows history of watched anime
     """
     # api request
     payload = {"media_types": "anime|drama",
-               "fields":      "media.name,media.media_id,media.description,media.episode_number,media.created,media.media_type,media.screenshot_image, \
-                               media.premium_only,media.premium_available,media.available,media.premium_available,media.duration, \
-                               series.name,series.series_id,series.year,series.publisher_name,series.rating,series.portrait_image"}
+               "fields":      "media.name,media.media_id,media.collection_id,media.collection_name,media.description,media.episode_number,media.created, \
+                               media.screenshot_image,media.premium_only,media.premium_available,media.available,media.premium_available,media.duration,media.playhead, \
+                               series.series_id,series.year,series.publisher_name,series.rating,series.genres,series.landscape_image"}
     req = api.request(args, "recently_watched", payload)
 
     # check for error
@@ -98,24 +142,181 @@
 
         # add to view
         view.add_item(args,
-                      {"title":       item["series"]["name"] + " #" + item["media"]["episode_number"] + " - " + item["media"]["name"],
-                       "tvshowtitle": item["series"]["name"],
-                       "duration":    item["media"]["duration"],
-                       "playcount":   1 if (100/int(item["media"]["duration"]))*int(item["playhead"]) > 90 else 0,
-                       "episode":     item["media"]["episode_number"],
-                       "episode_id":  item["media"]["media_id"],
-                       "series_id":   item["series"]["series_id"],
-                       "plot":        item["media"]["description"],
-                       "plotoutline": item["media"]["description"],
-                       "genre":       item["media"]["media_type"],
-                       "year":        item["series"]["year"],
-                       "aired":       item["media"]["created"][:10],
-                       "premiered":   item["media"]["created"][:10],
-                       "studio":      item["series"]["publisher_name"],
-                       "rating":      int(item["series"]["rating"])/10.0,
-                       "thumb":       item["media"]["screenshot_image"]["fwidestar_url"] if item["media"]["premium_only"] else item["media"]["screenshot_image"]["full_url"],
-                       "fanart":      item["series"]["portrait_image"]["full_url"],
-                       "mode":        "videoplay"},
+                      {"title":         item["media"]["collection_name"] + " #" + item["media"]["episode_number"] + " - " + item["media"]["name"],
+                       "tvshowtitle":   item["media"]["collection_name"],
+                       "duration":      item["media"]["duration"],
+                       "playcount":     1 if (100/float(item["media"]["duration"]))*int(item["media"]["playhead"]) > 90 else 0,
+                       "episode":       item["media"]["episode_number"],
+                       "episode_id":    item["media"]["media_id"],
+                       "collection_id": item["media"]["collection_id"],
+                       "series_id":     item["series"]["series_id"],
+                       "plot":          item["media"]["description"],
+                       "plotoutline":   item["media"]["description"],
+                       "genre":         ", ".join(item["series"]["genres"]),
+                       "year":          item["series"]["year"],
+                       "aired":         item["media"]["created"][:10],
+                       "premiered":     item["media"]["created"][:10],
+                       "studio":        item["series"]["publisher_name"],
+                       "rating":        int(item["series"]["rating"])/10.0,
+                       "thumb":         item["media"]["screenshot_image"]["fwidestar_url"] if item["media"]["premium_only"] else item["media"]["screenshot_image"]["full_url"],
+                       "fanart":        item["series"]["landscape_image"]["full_url"],
+                       "mode":          "videoplay"},
+                      isFolder=False)
+
+    view.endofdirectory()
+    return True
+
+
+def listSeries(args, mode):
+    """ view all anime from selected mode
+    """
+    # api request
+    payload = {"media_type": args.genre,
+               "filter":     mode,
+               "limit":      30,
+               "offset":     int(getattr(args, "offset", 0)),
+               "fields":     "series.name,series.series_id,series.description,series.year,series.publisher_name, \
+                              series.genres,series.portrait_image,series.landscape_image"}
+    req = api.request(args, "list_series", payload)
+
+    # check for error
+    if req["error"]:
+        view.add_item(args, {"title": args._addon.getLocalizedString(30061)})
+        view.endofdirectory()
+        return False
+
+    # display media
+    for item in req["data"]:
+        # add to view
+        view.add_item(args,
+                      {"title":       item["name"],
+                       "tvshowtitle": item["name"],
+                       "series_id":   item["series_id"],
+                       "plot":        item["description"],
+                       "plotoutline": item["description"],
+                       "genre":       ", ".join(item["genres"]),
+                       "year":        item["year"],
+                       "studio":      item["publisher_name"],
+                       "thumb":       item["portrait_image"]["full_url"],
+                       "fanart":      item["landscape_image"]["full_url"],
+                       "mode":        "series"},
+                      isFolder=True)
+
+    # show next page button
+    if len(req["data"]) >= 30:
+        view.add_item(args,
+                      {"title":  args._addon.getLocalizedString(30044),
+                       "offset": int(getattr(args, "offset", 0)) + 30,
+                       "mode":   args.mode},
+                      isFolder=True)
+
+    view.endofdirectory()
+    return True
+
+
+def listFilter(args, mode):
+    """ view all anime from selected mode
+    """
+    # test if filter is selected
+    if hasattr(args, "search"):
+        return listSeries(args, "tag:" + args.search)
+
+    # api request
+    payload = {"media_type": args.genre}
+    req = api.request(args, "categories", payload)
+
+    # check for error
+    if req["error"]:
+        view.add_item(args, {"title": args._addon.getLocalizedString(30061)})
+        view.endofdirectory()
+        return False
+
+    # display media
+    for item in req["data"][mode]:
+        # add to view
+        view.add_item(args,
+                      {"title":  item["label"],
+                       "search": item["tag"],
+                       "mode":   args.mode},
+                      isFolder=True)
+
+    view.endofdirectory()
+    return True
+
+
+def viewSeries(args):
+    """ view all seasons/arcs of an anime
+    """
+    # api request
+    payload = {"series_id": args.series_id,
+               "fields":    "collection.name,collection.collection_id,collection.description,collection.media_type,collection.created, \
+                             collection.season,collection.complete,collection.portrait_image,collection.landscape_image"}
+    req = api.request(args, "list_collections", payload)
+
+    # check for error
+    if req["error"]:
+        view.add_item(args, {"title": args._addon.getLocalizedString(30061)})
+        view.endofdirectory()
+        return False
+
+    # display media
+    for item in req["data"]:
+        # add to view
+        view.add_item(args,
+                      {"title":         item["name"],
+                       "tvshowtitle":   item["name"],
+                       "season":        item["season"],
+                       "collection_id": item["collection_id"],
+                       "series_id":     args.series_id,
+                       "plot":          item["description"],
+                       "plotoutline":   item["description"],
+                       "genre":         item["media_type"],
+                       "aired":         item["created"][:10],
+                       "premiered":     item["created"][:10],
+                       "status":        u"Completed" if item["complete"] else u"Continuing",
+                       "thumb":         item["portrait_image"]["full_url"] if item["portrait_image"] else args.thumb,
+                       "fanart":        item["landscape_image"]["full_url"] if item["landscape_image"] else args.fanart,
+                       "mode":          "episodes"},
+                      isFolder=True)
+
+    view.endofdirectory()
+    return True
+
+
+def viewEpisodes(args):
+    """ view all episodes of season
+    """
+    # api request
+    payload = {"collection_id": args.collection_id,
+               "fields":        "media.name,media.media_id,media.collection_id,media.collection_name,media.description,media.episode_number,media.created,media.series_id, \
+                                 media.screenshot_image,media.premium_only,media.premium_available,media.available,media.premium_available,media.duration,media.playhead"}
+    req = api.request(args, "list_media", payload)
+
+    # check for error
+    if req["error"]:
+        view.add_item(args, {"title": args._addon.getLocalizedString(30061)})
+        view.endofdirectory()
+        return False
+
+    # display media
+    for item in req["data"]:
+        # add to view
+        view.add_item(args,
+                      {"title":         item["collection_name"] + " #" + item["episode_number"] + " - " + item["name"],
+                       "tvshowtitle":   item["collection_name"],
+                       "duration":      item["duration"],
+                       "playcount":     1 if (100/float(item["duration"]))*int(item["playhead"]) > 90 else 0,
+                       "episode":       item["episode_number"],
+                       "episode_id":    item["media_id"],
+                       "collection_id": args.collection_id,
+                       "series_id":     item["series_id"],
+                       "plot":          item["description"],
+                       "plotoutline":   item["description"],
+                       "aired":         item["created"][:10],
+                       "premiered":     item["created"][:10],
+                       "thumb":         item["screenshot_image"]["fwidestar_url"] if item["premium_only"] else item["screenshot_image"]["full_url"],
+                       "fanart":        args.fanart,
+                       "mode":          "videoplay"},
                       isFolder=False)
 
     view.endofdirectory()
@@ -161,7 +362,7 @@
                 return
 
         # ask if user want to continue playback
-        resume = (100/int(req["data"]["duration"])) * int(req["data"]["playhead"])
+        resume = (100/float(req["data"]["duration"])) * int(req["data"]["playhead"])
         if resume >= 5 and resume <= 90:
             player.pause()
             if xbmcgui.Dialog().yesno(args._addonname, args._addon.getLocalizedString(30065) % resume):

--- a/resources/lib/crunchyroll.py
+++ b/resources/lib/crunchyroll.py
@@ -128,7 +128,7 @@
     elif mode == "queue":
         controller.showQueue(args)
     elif mode == "search":
-        controller.showSearch(args)
+        controller.searchAnime(args)
     elif mode == "history":
         controller.showHistory(args)
     elif mode == "random":
@@ -139,19 +139,27 @@
     elif mode == "drama":
         showMainCategory(args, "drama")
 
+    elif mode == "featured":
+        controller.listSeries(args, "featured")
     elif mode == "popular":
         controller.listSeries(args, "popular")
-    elif mode == "simulcasts":
-        controller.listSeries(args, "simulcasts")
+    elif mode == "simulcast":
+        controller.listSeries(args, "simulcast")
     elif mode == "updated":
         controller.listSeries(args, "updated")
-    elif mode == "alphabetical":
-        controller.listAlphabetical(args)
-    elif mode == "genres":
-        controller.listGenres(args)
-    elif mode == "seasons":
-        controller.listSeasons(args)
-
+    elif mode == "newest":
+        controller.listSeries(args, "newest")
+    elif mode == "alpha":
+        controller.listSeries(args, "alpha")
+    elif mode == "season":
+        controller.listFilter(args, "season")
+    elif mode == "genre":
+        controller.listFilter(args, "genre")
+
+    elif mode == "series":
+        controller.viewSeries(args)
+    elif mode == "episodes":
+        controller.viewEpisodes(args)
     elif mode == "videoplay":
         controller.startplayback(args)
     else:
@@ -189,28 +197,36 @@
     """Show main category
     """
     view.add_item(args,
+                  {"title": args._addon.getLocalizedString(30058),
+                   "mode":  "featured",
+                   "genre": genre})
+    view.add_item(args,
                   {"title": args._addon.getLocalizedString(30052),
                    "mode":  "popular",
                    "genre": genre})
     view.add_item(args,
                   {"title": args._addon.getLocalizedString(30053),
-                   "mode":  "simulcasts",
+                   "mode":  "simulcast",
                    "genre": genre})
     view.add_item(args,
                   {"title": args._addon.getLocalizedString(30054),
                    "mode":  "updated",
                    "genre": genre})
     view.add_item(args,
+                  {"title": args._addon.getLocalizedString(30059),
+                   "mode":  "newest",
+                   "genre": genre})
+    view.add_item(args,
                   {"title": args._addon.getLocalizedString(30055),
-                   "mode":  "alphabetical",
+                   "mode":  "alpha",
+                   "genre": genre})
+    view.add_item(args,
+                  {"title": args._addon.getLocalizedString(30057),
+                   "mode":  "season",
                    "genre": genre})
     view.add_item(args,
                   {"title": args._addon.getLocalizedString(30056),
-                   "mode":  "genres",
-                   "genre": genre})
-    view.add_item(args,
-                  {"title": args._addon.getLocalizedString(30057),
-                   "mode":  "seasons",
+                   "mode":  "genre",
                    "genre": genre})
     view.endofdirectory()