# -*- coding: utf-8 -*-
# Moovida - Home multimedia server
# Copyright (C) 2006-2009 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Moovida with Fluendo's plugins.
#
# The GPL part of Moovida is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Moovida" in the root directory of this distribution package
# for details on that license.

from elisa.core import common
from elisa.core.media_uri import MediaUri
from elisa.core.utils import defer
from elisa.core.utils.text import name_to_shortcut

from elisa.plugins.base.models.audio import TrackModel
from elisa.plugins.base.models.media import PlayableModel
from elisa.plugins.base.models.device import VolumeModel
from elisa.plugins.base.messages.device import NewDeviceDetected

from elisa.plugins.poblesec.base.list import BaseListController
from elisa.plugins.poblesec.base.list_switcher import ListSwitcherController
from elisa.plugins.poblesec.music_library import ArtistsViewMode, \
                                                 AlbumsViewMode, \
                                                 TracksViewMode

from elisa.plugins.poblesec.base.preview_list import \
    MenuItemPreviewListController, DoubleLineMenuItemPreviewListController
from elisa.plugins.poblesec.base.coverflow import \
    ImageWithReflectionCoverflowController
from elisa.plugins.poblesec.base.grid import GridItemGridController
from elisa.plugins.poblesec.link import DeviceLink

from twisted.internet import task

def ipod_decorator(controller):
    """
    Adds an iPod entry to the music menu if there is an ipod plugged in.
    """
    uri = MediaUri("volumes://?filter=ipod")
    model, dfr = common.application.resource_manager.get(uri, None)

    def add_link(model):
        """
        Adds a link to the controller for the iPod described in C{model}.
        """
        link = DeviceLink(model.udi)
        link.controller_path = "/poblesec/music/ipod"
        link.icon = "elisa.plugins.ipod.ipod"
        uri = MediaUri({'scheme': 'ipod',
                        'host': '',
                        'path': model.mount_point})
        uri.set_param('action', 'tracks')
        uri.set_param('search', 'artist')
        link.controller_args = {'uri': uri}
        link.label = model.name
        controller.model.append(link)


    def do_list_hardware(model):
        devices = sorted(model.devices, key=lambda i: i.name.lower())

        for dev in devices:
            if dev.mount_point != None:
                add_link(dev)

    dfr.addCallback(do_list_hardware)

    def on_device_added(message, sender):
        if message.model.protocol == 'ipod' \
          and message.model.mount_point != None:
            add_link(message.model)

    bus = common.application.bus
    bus.register(on_device_added, NewDeviceDetected)

    def on_clean(controller):
        bus.unregister(on_device_added)
        return defer.succeed(None)

    controller.connect('clean', on_clean)

    return dfr

class ArtistsIpodController(BaseListController):

    def initialize(self, uri):
        deferred = super(ArtistsIpodController, self).initialize()
        self.uri = uri

        def get_artists(self):
            model, dfr = common.application.resource_manager.get(self.uri)
            return dfr

        def got_artists(model):
            artists = model.artists

            def fix_models():
                for artist_model in artists:
                    uri = MediaUri(self.uri)
                    uri.set_param('action', 'tracks')
                    uri.set_param('search', 'albums')
                    uri.set_param('artist', artist_model.name)
                    artist_model.elisa_uri = uri
                    yield artist_model

            def models_fixed(result, artists):
                artists = sorted(artists, key=lambda a: a.name.lower())
                self.model.extend(artists)
                return self

            fix_models_deferred = task.coiterate(fix_models())
            fix_models_deferred.addCallback(models_fixed, artists)
            return fix_models_deferred

        deferred.addCallback(get_artists)
        deferred.addCallback(got_artists)
        return deferred

    def node_clicked(self, widget, item):
        browser = self.frontend.retrieve_controllers('/poblesec/browser')[0]
        controller_path = '/poblesec/music/ipod/albums'
        dfr = browser.history.append_controller(controller_path,
                                                item.name, artist=item)

class ArtistsIpodPreviewListController(ArtistsIpodController, MenuItemPreviewListController):
    view_mode = ArtistsViewMode
    fastscroller_enabled = True

    def get_shortcut_for_item(self, item):
        return name_to_shortcut(item.name)

class ArtistsIpodCoverflowController(ArtistsIpodController, ImageWithReflectionCoverflowController):
    view_mode = ArtistsViewMode

class ArtistsIpodGridController(ArtistsIpodController, GridItemGridController):
    view_mode = ArtistsViewMode

class ArtistsIpodListSwitcherController(ListSwitcherController):
    modes = [ArtistsIpodPreviewListController,
             ArtistsIpodCoverflowController,
             ArtistsIpodGridController]
    default_mode = ArtistsIpodPreviewListController


class AlbumsIpodController(BaseListController):

    def initialize(self, artist):
        deferred = super(AlbumsIpodController, self).initialize()
        self.artist = artist

        def get_albums(self):
            model, dfr = common.application.resource_manager.get(self.artist.elisa_uri)
            return dfr

        def got_albums(albums_list_model):
            albums = albums_list_model.albums

            def fix_models():
                for album_model in albums:
                    album_model.name = album_model.album
                    uri = MediaUri(self.artist.elisa_uri)
                    uri.set_param('action', 'tracks')
                    uri.set_param('search', 'songs')
                    uri.set_param('album', album_model.name)
                    album_model.elisa_uri = uri
                    yield album_model

            def models_fixed(result, albums):
                albums = sorted(albums, key=lambda a: a.name.lower())
                self.model.extend(albums)
                return self

            fix_models_deferred = task.coiterate(fix_models())
            fix_models_deferred.addCallback(models_fixed, albums)
            return fix_models_deferred

        deferred.addCallback(get_albums)
        deferred.addCallback(got_albums)
        return deferred

    def node_clicked(self, widget, item):
        browser = self.frontend.retrieve_controllers('/poblesec/browser')[0]
        controller_path = '/poblesec/music/ipod/tracks'
        dfr = browser.history.append_controller(controller_path,
                                                item.name, album=item)

class AlbumsIpodPreviewListController(AlbumsIpodController, MenuItemPreviewListController):
    view_mode = AlbumsViewMode

class AlbumsIpodCoverflowController(AlbumsIpodController, ImageWithReflectionCoverflowController):
    view_mode = AlbumsViewMode

class AlbumsIpodGridController(AlbumsIpodController, GridItemGridController):
    view_mode = AlbumsViewMode

class AlbumsIpodListSwitcherController(ListSwitcherController):
    modes = [AlbumsIpodPreviewListController,
             AlbumsIpodCoverflowController,
             AlbumsIpodGridController]
    default_mode = AlbumsIpodPreviewListController

class TracksIpodController(BaseListController):

    def initialize(self, album):
        deferred = super(TracksIpodController, self).initialize()
        self.album = album

        def get_tracks(self):
            model, dfr = common.application.resource_manager.get(self.album.elisa_uri)
            return dfr

        def got_tracks(tracks_list_model):
            tracks = sorted(tracks_list_model.songs,
                            key=lambda i: i.track_number)
            self.model.extend(tracks)
            return self

        deferred.addCallback(get_tracks)
        deferred.addCallback(got_tracks)
        return deferred

    def node_clicked(self, widget, item):
        self.play_audio(item)

    def play_audio(self, item):
        player = self.frontend.retrieve_controllers('/poblesec/music_player')[0]

        # Enqueue and play the clicked item
        playable_model = PlayableModel()
        playable_model.uri = item.playable_uri
        playable_model.title = item.title
        player.player.play_model(playable_model)

        main = self.frontend.retrieve_controllers('/poblesec')[0]
        main.show_music_player()

        # Enqueue all the following items of the container
        index = self.model.index(item)
        for item in self.model[index+1:]:
            if not isinstance(item, TrackModel):
                continue
            playable_model = PlayableModel()
            playable_model.uri = item.playable_uri
            playable_model.title = item.title
            player.player.enqueue_to_playlist(playable_model)

class TracksIpodPreviewListController(TracksIpodController, MenuItemPreviewListController):
    view_mode = TracksViewMode

class TracksIpodCoverflowController(TracksIpodController, ImageWithReflectionCoverflowController):
    view_mode = TracksViewMode

class TracksIpodGridController(TracksIpodController, GridItemGridController):
    view_mode = TracksViewMode

class TracksIpodListSwitcherController(ListSwitcherController):
    modes = [TracksIpodPreviewListController,
             TracksIpodCoverflowController,
             TracksIpodGridController]
    default_mode = TracksIpodPreviewListController
