# -*- 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.

# Author: Guido Amoruso <guidonte@fluendo.com>

from elisa.core.common import application
from elisa.core.utils import defer
from elisa.core.utils.i18n import install_translation

from elisa.plugins.database.models import PhotoAlbum
from elisa.plugins.database.models import Artist
from elisa.plugins.database.models import MusicAlbum
from elisa.plugins.database.models import MusicTrack
from elisa.plugins.database.models import File

import dbus


_ = install_translation('poblesec')


class PhotoAlbumNotFound(Exception):
    pass


class MusicAlbumNotFound(Exception):
    pass


class SectionNotFound(Exception):
    pass


class BrowserImpl(object):
    def __init__(self, browser):
        self.browser = browser

    def _append_controller_cb(self, result, path, label, **kwargs):
        return self.browser.history.append_controller(path, label, **kwargs)

    def browse_photo_album(self, album_name):
        dfr = application.store.find(PhotoAlbum, PhotoAlbum.name == album_name)

        def got_album(result_set):
            if len(result_set) == 0:
                return defer.fail(PhotoAlbumNotFound(album_name))

            album = result_set[0]

            dfr = self.browse_section('Pictures')
            dfr.addCallback(self._append_controller_cb,
                            '/poblesec/database/photo_library',
                            _('Photo Library'))
            dfr.addCallback(self._append_controller_cb,
                            '/poblesec/database/photo/albums',
                            _('Browse by Albums'))
            dfr.addCallback(self._append_controller_cb,
                            '/poblesec/database/photo/list',
                            album.name,
                            album=album)
            return dfr

        dfr.addCallback(lambda rs: rs.all())
        dfr.addCallback(got_album)
        return dfr

    def start_photo_album_slideshow(self, album_name):
        def start_slideshow(controller):
            # FIXME: to be re-implemented.
            raise NotImplementedError()

        dfr = self.browse_photo_album(album_name)
        return dfr.addCallback(start_slideshow)

    def browse_music_album(self, artist_name, album_name):
        self._artist = None
        message = "'%s' by '%s'" % (album_name, artist_name)

        def got_artist(result_set):
            if len(result_set) == 0:
                return defer.fail(MusicAlbumNotFound(message))

            self._artist = result_set[0]
            return self._artist.tracks.find(MusicTrack.file_path == File.path,
                                            File.hidden == False)

        def got_tracks(result_set):
            return result_set.values(MusicTrack.album_name)

        def get_albums(album_names):
            if len(album_names) == 0:
                return defer.fail(MusicAlbumNotFound(message))

            # Search for album_name in the artist's albums
            dfr = application.store.find(MusicAlbum,
                                         MusicAlbum.name.is_in(album_names),
                                         MusicAlbum.name == album_name)
            dfr.addCallback(lambda rs: rs.all())
            return dfr

        def got_albums(albums):
            if len(albums) == 0:
                return defer.fail(MusicAlbumNotFound(message))

            album = albums[0]

            dfr = self.browse_section('Music')
            dfr.addCallback(self._append_controller_cb,
                            '/poblesec/database/music_library',
                            _('Music Library'))
            dfr.addCallback(self._append_controller_cb,
                            '/poblesec/database/music/artists',
                            _('Artists'))
            dfr.addCallback(self._append_controller_cb,
                            '/poblesec/database/music/albums',
                            self._artist.name,
                            artist=self._artist)
            dfr.addCallback(self._append_controller_cb,
                            '/poblesec/database/album/tracks',
                            album.name,
                            album=album)
            return dfr

        dfr = application.store.find(Artist, Artist.name == artist_name)
        dfr.addCallback(lambda rs: rs.all())
        dfr.addCallback(got_artist)
        dfr.addCallback(got_tracks)
        dfr.addCallback(get_albums)
        dfr.addCallback(got_albums)
        return dfr

    def browse_section(self, section_name):
        sections = {'Music': ('/poblesec/music_menu', _('Music')),
                    'Video': ('/poblesec/video_menu', _('Video')),
                    'Pictures': ('/poblesec/pictures_menu', _('Pictures'))}

        # try to hide the player
        main = self.browser.frontend.retrieve_controllers('/poblesec')[0]
        main.hide_current_player()

        if section_name not in sections:
            return defer.fail(SectionNotFound(section_name))

        if self.browser.history.current.path == sections[section_name][0]:
            return defer.succeed(None)

        self.browser.history.clear()

        # Select the corresponding item in Elisa's main menu
        for i, link in enumerate(self.browser.history.current.model):
            if link.label == sections[section_name][1]:
                self.browser.history.current.menu.selected_item_index = i
                break

        dfr = self.browser.history.append_controller(sections[section_name][0],
                                                     sections[section_name][1])
        return dfr


class DBusBrowser(dbus.service.Object):
    interface = 'com.fluendo.Elisa.Plugins.Poblesec.Browser'

    def __init__(self, browser, *args, **kw):
        dbus.service.Object.__init__(self, *args, **kw)
        self.impl = BrowserImpl(browser)

    @dbus.service.method(dbus_interface=interface,
                         in_signature='s', out_signature='')
    def browse_photo_album(self, album_name):
        dfr = self.impl.browse_photo_album(album_name)

    @dbus.service.method(dbus_interface=interface,
                         in_signature='s', out_signature='')
    def start_photo_album_slideshow(self, album_name):
        dfr = self.impl.start_photo_album_slideshow(album_name)

    @dbus.service.method(dbus_interface=interface,
                         in_signature='ss', out_signature='')
    def browse_music_album(self, artist_name, album_name):
        dfr = self.impl.browse_music_album(artist_name, album_name)

    @dbus.service.method(dbus_interface=interface,
                         in_signature='s', out_signature='')
    def browse_section(self, section_name):
        dfr = self.impl.browse_section(section_name)
