#!/usr/bin/python
import logging
import urllib
import sys
import time
import optparse

from lxml import etree

from Growl import GrowlNotifier

API_KEY="REPLACE_WITH_YOUR_API_KEY"

class Roar():
    """
    Simple class to query the last.fm api for the currently playing
    song for a user and show the artist and title using Growl

    Note: I know that the data also is availble in json format, removing the
    need for lxml, but the json serialization is ugly as sin....
    """

    def __init__(self, user):
        logging.debug("Creating Roar client for user '%s'" % user)
        self._last_artist = None
        self._last_title = None
        api_data = {
            "user": user,
            "method": "user.getrecenttracks",
            "nowplaying": "true",
            "limit": "1",
            "api_key": API_KEY,
        }
        self._url = "http://ws.audioscrobbler.com/2.0/?" + urllib.urlencode(api_data)
        self._growler = GrowlNotifier(applicationName='Roar', notifications=["info"])
        self._growler.register()

    def _get(self, node):
        """Get node text helper"""

        return node.text if node is not None else None

    def run(self, interval):
        """Fetch data indefinitely each 'internal' seconds"""

        while True:
            self.fetch()
            time.sleep(interval)

    def fetch(self):
        """Fetch data and notify if it has changed since last call"""

        logging.debug("Calling API")
        try:
            response = urllib.urlopen(self._url)
        except IOError, e:
            logging.warning("Got error opening API url: " + e)
            return

        if (response.getcode() != 200):
            logging.warning("Response error: %d" % response.getcode())
            return

        xml = etree.parse(response)
        track = xml.xpath("//track[@nowplaying='true']")
        if not len(track):
            logging.debug("No currently playing track")
            return

        track = track[0]
        title = self._get(track.find("name")) or "Unknown Title"
        artist = self._get(track.find("artist")) or "Unknown Artist"

        if title == self._last_title and artist == self._last_artist:
            logging.debug("Nothing changed")
            return

        self._last_artist = artist
        self._last_title = title

        icon_url = self._get(track.find("image[@size='medium']"))
        icon = None
        if icon_url:
            logging.debug("Fetching icon (%s)" % icon_url)
            try:
                icon = urllib.urlopen(icon_url).read()
            except IOError, e:
                logging.warning("Could not fetch URL: " + e)

        logging.debug("Notifying: %s - %s" % (artist, title))
        self._growler.notify("info", title, artist, icon=icon)

if __name__ == "__main__":
    parser = optparse.OptionParser()
    parser.add_option("-d", "--debug",
                      action="store_true", dest="debug", default=False,
                      help="Turn on debugging")
    parser.add_option("-i", "--interval",
                      type="int", dest="interval", default=30,
                      help="Update interval, in seconds")
    (options, args) = parser.parse_args()
    if options.debug:
        logging.basicConfig(level=logging.DEBUG)

    if len(args) < 1:
        print "ERROR: Please give last.fm user name as the first argument\n"
        parser.print_help()
        exit()

    r = Roar(args[0])
    r.run(options.interval)