#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals

from .. import utils, variables as v, app


def _transcode_image_path(key, AuthToken, path, width, height):
    """
    Transcode Image support

    parameters:
        key
        AuthToken
        path - source path of current XML: path[srcXML]
        width
        height
    result:
        final path to image file
    """
    # external address - can we get a transcoding request for external images?
    if key.startswith('http'):
        path = key
    elif key.startswith('/'):  # internal full path.
        path = 'http://127.0.0.1:32400' + key
    else:  # internal path, add-on
        path = 'http://127.0.0.1:32400' + path + '/' + key
    # This is bogus (note the extra path component) but ATV is stupid when it
    # comes to caching images, it doesn't use querystrings. Fortunately PMS is
    # lenient...
    transcode_path = ('/photo/:/transcode/%sx%s/%s'
                      % (width, height, utils.quote_plus(path)))
    args = {
        'width': width,
        'height': height,
        'url': path
    }
    if AuthToken:
        args['X-Plex-Token'] = AuthToken
    return utils.extend_url(transcode_path, args)


class File(object):
    def fullpath(self, force_first_media=True, force_addon=False,
             direct_paths=None, omit_check=False, force_check=False):
        """
        Returns a "fully qualified path" add-on paths or direct paths
        depending on the current settings as the tupple
            (fullpath, path, filename)
        as unicode. Add-on paths are returned as a fallback. Returns None
        if something went wrong.

        firce_first_media=False prompts the user to choose which version of the
                                media should be returned, if several are present
        force_addon=True will always return the add-on path
        direct_path=True if you're calling from another Plex python
                         instance - because otherwise direct paths will
                         evaluate to False!
        """
        direct_paths = app.SYNC.direct_paths if direct_paths is None \
            else direct_paths
        if (not direct_paths or force_addon or
                self.plex_type == v.PLEX_TYPE_CLIP):
            if self.plex_type == v.PLEX_TYPE_SONG:
                return self._music_addon_paths(force_first_media)
            if self.plex_type == v.PLEX_TYPE_EPISODE:
                # need to include the plex show id in the path
                path = ('plugin://plugin.video.plexkodiconnect.tvshows/%s/'
                        % self.grandparent_id())
            else:
                path = 'plugin://%s/' % v.ADDON_TYPE[self.plex_type]
            # Filename in Kodi will end with actual filename - hopefully
            # this is useful for other add-ons
            filename = self.file_path(force_first_media=force_first_media)
            if filename:
                if '/' in filename:
                    filename = filename.rsplit('/', 1)[1]
                else:
                    filename = filename.rsplit('\\', 1)[1]
                entirepath = ('%s?mode=play&plex_id=%s&plex_type=%s&filename=%s'
                        % (path, self.plex_id, self.plex_type, filename))
            else:
                # E.g. clips or albums
                entirepath = ('%s?mode=play&plex_id=%s&plex_type=%s'
                        % (path, self.plex_id, self.plex_type))
            # For Kodi DB, we need to safe the ENTIRE path for filenames
            filename = entirepath
        else:
            entirepath = self.validate_playurl(
                self.file_path(force_first_media=force_first_media),
                self.plex_type,
                force_check=force_check,
                omit_check=omit_check)
            try:
                if '/' in entirepath:
                    filename = entirepath.rsplit('/', 1)[1]
                else:
                    filename = entirepath.rsplit('\\', 1)[1]
            except (TypeError, IndexError):
                # Fallback to add-on paths
                return self.fullpath(force_first_media=force_first_media,
                                     force_addon=True)
            path = utils.rreplace(entirepath, filename, "", 1)
        return entirepath, path, filename

    def _music_addon_paths(self, force_first_media):
        """
        For songs only. Normal add-on paths plugin://... don't work with the
        Kodi music DB, hence use a "direct" url to the music file on the PMS.
        """
        if self.mediastream is None and force_first_media is False:
            if self.mediastream_number() is None:
                return
        streamno = 0 if force_first_media else self.mediastream
        entirepath = "%s%s" % (app.CONN.server,
                               self.xml[streamno][self.part].get('key'))
        entirepath = self.attach_plex_token_to_url(entirepath)
        path, filename = entirepath.rsplit('/', 1)
        return entirepath, path + '/', filename

    def directory_path(self, section_id=None, plex_type=None, old_key=None,
                       synched=True):
        key = self.xml.get('fastKey')
        if not key:
            key = self.xml.get('key')
            if old_key:
                key = '%s/%s' % (old_key, key)
            elif not key.startswith('/'):
                key = '/library/sections/%s/%s' % (section_id, key)
        params = {
            'mode': 'browseplex',
            'key': key
        }
        if plex_type or self.plex_type:
            params['plex_type'] = plex_type or self.plex_type
        if not synched:
            # No item to be found in the Kodi DB
            params['synched'] = 'false'
        if self.xml.get('prompt'):
            # User input needed, e.g. search for a movie or episode
            params['prompt'] = self.xml.get('prompt')
        if section_id:
            params['id'] = section_id
        return utils.extend_url('plugin://%s/' % v.ADDON_ID, params)

    def file_name(self, force_first_media=False):
        """
        Returns only the filename, e.g. 'movie.mkv' as unicode or None if not
        found
        """
        ans = self.file_path(force_first_media=force_first_media)
        if ans is None:
            return
        if "\\" in ans:
            # Local path
            filename = ans.rsplit("\\", 1)[1]
        else:
            try:
                # Network share
                filename = ans.rsplit("/", 1)[1]
            except IndexError:
                # E.g. certain Plex channels
                filename = None
        return filename

    def file_path(self, force_first_media=False):
        """
        Returns the direct path to this item, e.g. '\\NAS\movies\movie.mkv'
        as unicode or None

        force_first_media=True:
            will always use 1st media stream, e.g. when several different
            files are present for the same PMS item
        """
        if self.mediastream is None and force_first_media is False:
            if self.mediastream_number() is None:
                return
        try:
            if force_first_media is False:
                ans = self.xml[self.mediastream][self.part].attrib['file']
            else:
                ans = self.xml[0][self.part].attrib['file']
        except (TypeError, AttributeError, IndexError, KeyError):
            return
        return ans

    def get_picture_path(self):
        """
        Returns the item's picture path (transcode, if necessary) as string.
        Will always use addon paths, never direct paths
        """
        path = self.xml[0][0].get('key')
        extension = path[path.rfind('.'):].lower()
        if app.SYNC.force_transcode_pix or extension not in v.KODI_SUPPORTED_IMAGES:
            # Let Plex transcode
            # max width/height supported by plex image transcoder is 1920x1080
            path = app.CONN.server + _transcode_image_path(
                path,
                app.ACCOUNT.pms_token,
                "%s%s" % (app.CONN.server, path),
                1920,
                1080)
        else:
            path = self.attach_plex_token_to_url('%s%s' % (app.CONN.server, path))
        # Attach Plex id to url to let it be picked up by our playqueue agent
        # later
        return '%s&plex_id=%s' % (path, self.plex_id)
