import re
import math
import random
import requests
import requests.cookies

from youtube_dl.utils import ExtractorError
from youtube_dl.extractor.common import InfoExtractor

from .private_api import RdioSession


USER_AGENT = (u"Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.1"
              u" (KHTML, like Gecko) Chrome/13.0.782.99 Safari/535.1")


def random_player_id():
    return unicode(int(math.floor(random.random() * 10000000)))


class RdioIE(InfoExtractor):
    IE_DESC = u'Rdio'

    @classmethod
    def suitable(cls, url):
        valid_urls = {
            'track': (
                r'^(?:https?://)?(?:www\.)?rdio\.com/artist/(?P<artist>[^\/]+)/'
                r'album/(?P<album>[^\/]+)/track/(?P<track>[^\/]+)/?$'
            ),
            'album': (
                r'^(?:https?://)?(?:www\.)?rdio\.com/artist/(?P<artist>[^\/]+)/'
                r'album/(?P<album>[^\/]+)/?$'
            ),
            'playlist': (
                r'^(?:https?://)?(?:www\.)?rdio\.com/people/(?P<owner>[^\/]+)/'
                r'playlists/(?P<playlist_id>[^\/]+)/'
                r'(?P<playlist_name>[^\/]+)/?$'
            ),
            'short': r'^(?:https?://)?rd\.io/x/[^\/]+/?$',
            }

        return any((re.match(test_re, url) for test_re in valid_urls.values()))

    def __init__(self, storage, username, password, quality):
        super(RdioIE, self).__init__(self)

        user_state = storage.load(username)

        self.rdio = RdioSession()
        self.quality = quality

        if user_state:
            self.rdio._authorization_key = user_state.get('authorization_key')
            cookies = user_state.get('cookies', {})
            self.rdio.cookies = requests.cookies.cookiejar_from_dict(cookies)

        if not self.rdio._authorization_key:
            self.rdio.sign_in(username, password)
            storage.save(username, {
                'cookies': dict(self.rdio.cookies),
                'authorization_key': self.rdio._authorization_key,
                })

    def _get_object_from_url(self, url):
        """Get a object (track, album, playlist) from the given URL.
        """
        result = self.rdio.api_call('getObjectFromUrl', url=url,
                                    extras=['tracks'], referer=url)
        return result.json()

    def _get_playback_info_through_http(self, key, type=u'mp3-high'):
        player_name = '_web_{0}'.format(random_player_id())

        playback_info = self.rdio.api_call('getPlaybackInfo',
                                           key=key,
                                           manualPlay=False,
                                           playerName=player_name,
                                           requiresUnlimited=False,
                                           finishedAd=False,
                                           type=type)

        playback_info = playback_info.json()

        if not playback_info.get('result'):
            reason = playback_info.get('message', u"Unknown error")
            raise ExtractorError(
                u"Failed to get playback information: `{0}'".format(reason))

        return dict(url=playback_info['result']['surl'])

    def _real_extract(self, url):
        obj = self._get_object_from_url(url)

        obj = obj.get('result')

        typ = obj['type']

        if typ == u't':
            return self._extract_track(obj)

        elif typ not in (u'a', u'p'):
            raise ExtractorError(u"Unknown object type: `{0}'".format(typ))

        # deal with playlists and albums
        tracks = obj.get('tracks', [])

        # XXX sometimes the result is a list, sometimes its a dict with an
        # items item
        if isinstance(tracks, dict):
            tracks = tracks.get('items', [])

        entries = [self.url_result(t['shortUrl'], video_id=t['key'])
                   for t in tracks]

        return self.playlist_result(entries, obj['key'], obj['name'])

    def _extract_track(self, track):
        ext, typ = {
            u'high': (u'mp3', u'mp3-high'),
            u'very-high': (u'mp4', u'aac-very-high'),
        }[self.quality]

        info = {
            'id': track['key'],
            'ext': ext,
            'title': track['name'],
            'artist': track['artist'],
            'album': track['album'],
            'album_artist': track.get('albumArtist'),
            'track_number': track.get('trackNum'),
            'uploader': track['artist'],
            'description': u'',
            'thumbnails': [
                {'width': 200, 'height': 200, 'url': track.get('icon'),
                 'id': u'{0}200'.format(track['albumKey'])},
                {'width': 400, 'height': 400, 'url': track.get('icon400'),
                 'id': u'{0}400'.format(track['albumKey'])},
            ]
        }

        playback_info = self._get_playback_info_through_http(track['key'], type=typ)

        info.update(playback_info)

        return info
