#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = "Dominik Minta"
__copyright__ = "Copyright 2012, Dominik Minta"
__email__ = "dominik@minta.it"
__license__ = "MIT"

import urllib
import re
from datetime import date
from HTMLParser import HTMLParser

class PolskieRadioPlaylistParser:
    """A simple downloader and parser for playlists published on Polskie Radio
    website.
    """

    __base_playlist_url = \
        'http://www.polskieradio.pl/Components/Playlist/AjaxPages/' \
        'AjaxPlaylist.aspx?'

    class PlaylistParser(HTMLParser):

        def __init__(self):
            HTMLParser.__init__(self)
            self.playlist = []
            self.__in_subplaylist_title_scope = False
            self.__in_playlist_scope = False
            self.__in_artist_tag = False
            self.__in_title_tag = False
            self.__in_subplaylist_title_tag = False
            self.__in_subplaylist_time_tag = False

        def handle_starttag(self, tag, attrs):
            if tag == 'div':
                for attr in attrs:
                    if attr[0] == 'class' and attr[1] == 'titlePlaylist':
                        self.__in_subplaylist_title_scope = True
                        self.__current_subplaylist = {}
            elif tag == 'ul':
                for attr in attrs:
                    if attr[0] == 'class' and attr[1] == 'ulPlaylist':
                        self.__in_playlist_scope = True
            elif tag == 'span' and (self.__in_playlist_scope
                                    or self.__in_subplaylist_title_scope):
                for attr in attrs:
                    if attr[0] == 'class':
                        if self.__in_subplaylist_title_scope:
                            self.__in_subplaylist_title_tag = \
                                                            attr[1] == 'bTitle'
                            self.__in_subplaylist_time_tag = attr[1] == 'bTime'
                        elif self.__in_playlist_scope:
                            self.__in_artist_tag = attr[1] == 'bArtist'
                            self.__in_title_tag = attr[1] == 'bTitle'
                        self.__data_buffer = []

        def handle_endtag(self, tag):
            if tag == 'div':
                if self.__in_subplaylist_title_scope:
                    self.__in_subplaylist_title_scope = False
            elif tag == 'ul':
                if self.__in_playlist_scope:
                    self.__in_playlist_scope = False
            elif tag == 'span':
                if self.__in_playlist_scope:
                    if self.__in_artist_tag or self.__in_title_tag:
                        data = ' '.join(self.__data_buffer)
                    if self.__in_title_tag:
                        self.__curr_title = data
                        self.__in_title_tag = False
                    elif self.__in_artist_tag:
                        self.__current_subplaylist['playlist'] \
                            .append({'artist': data, \
                                     'title': self.__curr_title})
                        self.__in_artist_tag = False
                elif self.__in_subplaylist_title_scope:
                    if self.__in_subplaylist_title_tag \
                        or self.__in_subplaylist_time_tag:
                        data = ' '.join(self.__data_buffer)
                    if self.__in_subplaylist_title_tag:
                        self.__current_subplaylist_title = data
                    elif self.__in_subplaylist_time_tag:
                        time = re.findall(
                            '[01][0-9]:[0-5][0-9]|2[0-3]:[0-5][0-9]', data)
                        self.__current_subplaylist.update({
                            'title': self.__current_subplaylist_title,
                            'time_from': time[0],
                            'time_to': time[1],
                            'playlist': [],
                        })
                        self.playlist.append(self.__current_subplaylist)

        def handle_data(self, data):
            if (self.__in_playlist_scope \
            and (self.__in_artist_tag or self.__in_title_tag)) \
            or (self.__in_subplaylist_title_scope \
                and (self.__in_subplaylist_title_tag \
                     or self.__in_subplaylist_time_tag)):
                self.__data_buffer.append(data.strip(';').lstrip().rstrip())

    @staticmethod
    def get_playlist_page_source(antenna, year, month, day):
        """Downloads and returns a playlist page source for specified antenna
        and date.
        """

        url = '{0}selectedDayDate={1:4}{2:02}{3:02}&antenna={4}' \
              .format(PolskieRadioPlaylistParser.__base_playlist_url,
                      year, month, day, antenna)
        sock = urllib.urlopen(url)
        source = sock.read()
        sock.close()
        return source

    @staticmethod
    def parse_playlist(antenna, year, month, day):
        """Downloads and returns a parsed playlist for specified antenna
        and date (year, month, day).
        """
        
        page = PolskieRadioPlaylistParser \
               .get_playlist_page_source(antenna, year, month, day)
        parser = PolskieRadioPlaylistParser.PlaylistParser()
        parser.feed(page)
        parser.close()
        return parser.playlist


def _test():
    import sys
    
    antenna = int(sys.argv[1]) if len(sys.argv[1:]) >= 1 else 1
    playlist_date = date(int(sys.argv[2]), int(sys.argv[3]), int(sys.argv[4])) \
                    if len(sys.argv[1:]) == 4 else date.today()
    
    playlist = PolskieRadioPlaylistParser \
               .parse_playlist(antenna, playlist_date.year, \
                               playlist_date.month, playlist_date.day)
               
    for subplaylist in playlist:
        print '{0} ({1} - {2})' \
              .format(subplaylist['title'], subplaylist['time_from'], \
                      subplaylist['time_to'])
        for track in subplaylist['playlist']:
            print '\t{0} - {1}'.format(track['artist'], track['title'])


if __name__ == '__main__':
    _test()
