# -*- 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.utils import defer

def end_callback_wrapper(deferred, controller):
    def wrapper(result):
        try:
            deferred.callback(controller)
        except defer.AlreadyCalledError:
            # was cancelled
            pass
    return wrapper

def cancel_wrapper(controller):
    def wrapper(dfr):
        controller.widget.animated.update_animation_settings(end_callback=None)
        controller.widget.animated.stop_animations()
        dfr.errback(defer.CancelledError())
    return wrapper

class Transition(object):
    def apply(self, controller):
        return defer.succeed(controller)

    def _stop(self, dfr, controller):
        dfr.errback(())

class FadeIn(Transition):
    def apply(self, controller):

        dfr = defer.Deferred(canceller=cancel_wrapper(controller))

        if not controller.widget.visible:
            controller.widget.opacity = 0
            controller.widget.visible = True

        end_animation = end_callback_wrapper(dfr, controller)

        controller.widget.animated.update_animation_settings(duration=600,
                end_callback=end_animation)

        if controller.widget.animated.opacity == 255:
            end_animation(None)
        else:
            controller.widget.animated.opacity = 255

        return dfr

class FadeOut(Transition):
    def apply(self, controller):

        dfr = defer.Deferred(canceller=cancel_wrapper(controller))

        controller.widget.animated.update_animation_settings(duration=400,
                end_callback=end_callback_wrapper(dfr, controller))
        controller.widget.animated.opacity = 0

        return dfr

class SlideLeftIn(Transition):
    def apply(self, controller):

        dfr = defer.Deferred(canceller=cancel_wrapper(controller))

        if not controller.widget.visible:
            controller.widget.opacity = 255
            controller.widget.x = -controller.widget.width
            controller.widget.visible = True

        if controller.widget.x == 0.0:
            dfr.callback(controller)
        else:
            controller.widget.animated.update_animation_settings(duration=400,
                        end_callback=end_callback_wrapper(dfr, controller))
            controller.widget.animated.x = 0.0

        return dfr

class SlideRightIn(Transition):
    def apply(self, controller):

        dfr = defer.Deferred(canceller=cancel_wrapper(controller))

        if not controller.widget.visible:
            controller.widget.opacity = 255
            controller.widget.x = 1.0
            controller.widget.visible = True

        if controller.widget.x == 0.0:
            dfr.callback(controller)
        else:
            controller.widget.animated.update_animation_settings(duration=400,
                    end_callback=end_callback_wrapper(dfr, controller))
            controller.widget.animated.x = 0.0

        return dfr

class SlideLeftOut(Transition):
    def apply(self, controller):

        dfr = defer.Deferred(canceller=cancel_wrapper(controller))

        controller.widget.animated.update_animation_settings(duration=400,
                end_callback=end_callback_wrapper(dfr, controller))
        controller.widget.animated.x = -controller.widget.width

        return dfr

class SlideRightOut(Transition):
    def apply(self, controller):

        dfr = defer.Deferred(canceller=cancel_wrapper(controller))

        controller.widget.animated.update_animation_settings(duration=400,
                end_callback=end_callback_wrapper(dfr, controller))
        controller.widget.animated.x = 1.0

        return dfr


class SoftFadeFrontIn(Transition):
    def apply(self, controller):
        dfr = defer.Deferred(canceller=cancel_wrapper(controller))

        if not controller.widget.visible:
            controller.widget.opacity = 0
            controller.widget.z = 100.0
            controller.widget.visible = True

        if controller.widget.z == 0.0:
            dfr.callback(controller)
        else:
            controller.widget.animated.setup_next_animations(duration=350,
                    end_callback=end_callback_wrapper(dfr, controller))
            controller.widget.animated.opacity = 255
            controller.widget.animated.z = 0.0

        return dfr

class SoftFadeBackIn(Transition):
    def apply(self, controller):

        dfr = defer.Deferred(canceller=cancel_wrapper(controller))

        if not controller.widget.visible:
            controller.widget.opacity = 0
            controller.widget.z = -100.0
            controller.widget.visible = True

        if controller.widget.z == 0.0:
            dfr.callback(controller)
        else:
            controller.widget.animated.setup_next_animations(duration=350,
                    end_callback=end_callback_wrapper(dfr, controller))
            controller.widget.animated.opacity = 255
            controller.widget.animated.z = 0.0

        return dfr

class SoftFadeFrontOut(Transition):
    def apply(self, controller):

        dfr = defer.Deferred(canceller=cancel_wrapper(controller))

        controller.widget.animated.setup_next_animations(duration=250,
                end_callback=end_callback_wrapper(dfr, controller))
        controller.widget.animated.opacity = 0
        controller.widget.animated.z = 100.0

        return dfr

class SoftFadeBackOut(Transition):
    def apply(self, controller):

        dfr = defer.Deferred(canceller=cancel_wrapper(controller))

        controller.widget.animated.setup_next_animations(duration=250,
                end_callback=end_callback_wrapper(dfr, controller))
        controller.widget.animated.opacity = 0
        controller.widget.animated.z = -100.0

        return dfr
