# -*- 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.
#
# Authors: Philippe Normand <philippe@fluendo.com>
#          Florian Boucault <florian@fluendo.com>

from elisa.plugins.poblesec.widgets.player.control_ribbon import Control
from elisa.plugins.pigment.widgets.const import *
from elisa.plugins.base.models import image

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

from elisa.plugins.database.models import Image as DBImage

_ = install_translation('poblesec')


class StopControl(Control):
    """
    Stop the playback of the current media.

    Its L{slave} passed to the constructor must be of type
    L{elisa.plugins.poblesec.slideshow.player.SlideshowController}.
    """

    caption = _("Stop")
    glyphs = \
            {STATE_NORMAL: 'elisa.plugins.poblesec.player.glyphs.stop_normal',
             STATE_SELECTED: 'elisa.plugins.poblesec.player.glyphs.stop_selected',
             STATE_PRESSED: 'elisa.plugins.poblesec.player.glyphs.stop_active',
            }

    def activate(self):
        self.slave.exit()
        return defer.succeed(None)

class RotationControl(Control):
    """
    Control for image rotation. When it's activated, it:

     - rotates 9O° clock-wise the various drawables showing the image in the UI
     - updates the orientation field of the image in the database if possible

    Its L{slave} passed to the constructor must be of type
    L{elisa.plugins.poblesec.slideshow.player.PlayerController}.
    """

    caption = _("Rotate")
    glyphs = \
            {STATE_NORMAL: 'elisa.plugins.poblesec.player.glyphs.rotate_normal',
             STATE_SELECTED: 'elisa.plugins.poblesec.player.glyphs.rotate_selected',
             STATE_PRESSED: 'elisa.plugins.poblesec.player.glyphs.rotate_active',
            }

    def _compute_next_orientation(self, orientation):
        # 90° clock-wise increments
        rotations = [image.ROTATED_0, image.ROTATED_90_CW,
                     image.ROTATED_180, image.ROTATED_90_CCW]
        current_index = rotations.index(orientation)
        next_index = (current_index + 1) % len(rotations)
        return rotations[next_index]

    def _save_to_database(self, image_from_database, next_orientation):
        if image_from_database is None:
            # The image is local but is not in the database.
            # That happens e.g. when a file was open or dragged'n dropped in
            # Elisa.
            return
        image_from_database.orientation = next_orientation
        store = common.application.store
        store.commit()

    def activate(self):
        model = self.slave.player.get_current_picture()

        # update model's orientation
        model.orientation = self._compute_next_orientation(model.orientation)
    
        # visually rotate the picture
        self.slave.player.rotate_current_picture(model.orientation)

        # save new orientation to database if possible
        store = common.application.store
        uri = model.references[-1]
        if store != None and uri.scheme == 'file':
            # database only support files
            dfr = store.get(DBImage, uri.path)
            dfr.addCallback(self._save_to_database, model.orientation)
            return dfr
        else:
            return defer.succeed(None)

class ShowNextControl(Control):
    """
    Show next picture of the slideshow, if there's any

    Its L{slave} passed to the constructor must be of type
    L{elisa.plugins.poblesec.slideshow.player.PlayerController}.
    """
    caption = _("Show Next")
    glyphs = \
            {STATE_NORMAL: 'elisa.plugins.poblesec.player.glyphs.next_normal',
             STATE_SELECTED: 'elisa.plugins.poblesec.player.glyphs.next_selected',
             STATE_PRESSED: 'elisa.plugins.poblesec.player.glyphs.next_active',
            }

    def activate(self):
        self.slave.player.next()
        return defer.succeed(None)

class ShowPreviousControl(Control):
    """
    Show the previous picture of the slideshow if the beginning of the
    list hasn't been reached yet.

    Its L{slave} passed to the constructor must be of type
    L{elisa.plugins.poblesec.slideshow.player.PlayerController}.
    """
    caption = _("Show Previous")
    glyphs = \
            {STATE_NORMAL: 'elisa.plugins.poblesec.player.glyphs.previous_normal',
             STATE_SELECTED: 'elisa.plugins.poblesec.player.glyphs.previous_selected',
             STATE_PRESSED: 'elisa.plugins.poblesec.player.glyphs.previous_active',
            }

    def activate(self):
        self.slave.player.previous()
        return defer.succeed(None)

class ToggleSlideshowControl(Control):
    """
    Set the slideshow to be the next one in the list of available slideshows.

    Its L{slave} passed to the constructor must be of type
    L{elisa.plugins.poblesec.slideshow.player.PlayerController}.
    """
    glyphs = \
            {STATE_NORMAL: 'elisa.plugins.poblesec.player.glyphs.toggle_effect_normal',
             STATE_SELECTED: 'elisa.plugins.poblesec.player.glyphs.toggle_effect_selected',
             STATE_PRESSED: 'elisa.plugins.poblesec.player.glyphs.toggle_effect_active',
            }

    def __init__(self, *args):
        super(ToggleSlideshowControl, self).__init__(*args)

        # FIXME: should disconnect from the signals on cleanup
        self.slave.player.connect('slideshow-changed',
                                  self._update)
        self.slave.player.connect('available-slideshows-changed',
                                  self._update)

        self._update(self.slave.player)

    def _update(self, player, dummy=None):
        current_slideshow = player.get_slideshow()
        slideshows = player.get_available_slideshows()

        index = slideshows.index(current_slideshow)

        self.caption = _("Slideshow Effect: %(name)s (%(index)d of %(count)d)") % \
                          {'name': current_slideshow.name,
                           'index': index+1,
                           'count': len(slideshows)}

    def activate(self):
        player = self.slave.player
        current_slideshow = player.get_slideshow()
        slideshows = player.get_available_slideshows()

        index = (slideshows.index(current_slideshow)+1)%len(slideshows)
        next_slideshow = slideshows[index]

        self.slave.player.set_slideshow(next_slideshow)
        return defer.succeed(None)
