/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_slideshow.hxx"

// must be first
#include <canvas/debug.hxx>
#include <tools/diagnose_ex.h>

#include <comphelper/anytostring.hxx>
#include <cppuhelper/exc_hlp.hxx>

#include <com/sun/star/awt/SystemPointer.hpp>
#include <com/sun/star/awt/MouseButton.hpp>
#include <com/sun/star/awt/MouseEvent.hpp>

#include <boost/bind.hpp>

#include "delayevent.hxx"
#include "usereventqueue.hxx"
#include "cursormanager.hxx"
#include "slideshowexceptions.hxx"

#include <vector>
#include <queue>
#include <map>
#include <functional>
#include <algorithm>


using namespace com::sun::star;

/* Implementation of UserEventQueue class */

namespace slideshow {
namespace internal {

namespace {

typedef std::vector<EventSharedPtr> ImpEventVector;
typedef std::queue<EventSharedPtr> ImpEventQueue;
typedef std::map<uno::Reference<animations::XAnimationNode>,
                 ImpEventVector> ImpAnimationEventMap;
typedef std::map<ShapeSharedPtr, ImpEventQueue,
                 Shape::lessThanShape> ImpShapeEventMap;

// MouseEventHandler base class, not consuming any event:
class MouseEventHandler_ : public MouseEventHandler
{
public:
    virtual bool handleMousePressed( awt::MouseEvent const& /*e*/ ) { return false;}
    virtual bool handleMouseReleased( awt::MouseEvent const& /*e*/) { return false;}
    virtual bool handleMouseEntered( awt::MouseEvent const& /*e*/ ) { return false;}
    virtual bool handleMouseExited( awt::MouseEvent const& /*e*/ ) { return false; }
    virtual bool handleMouseDragged( awt::MouseEvent const& /*e*/ ) { return false;}
    virtual bool handleMouseMoved( awt::MouseEvent const& /*e*/ ) { return false; }
};

/** @return one event has been posted
 */
template <typename ContainerT>
bool fireSingleEvent( ContainerT & rQueue, EventQueue & rEventQueue )
{
    // post next event in given queue:
    while (! rQueue.empty())
    {
        EventSharedPtr const pEvent(rQueue.front());
        rQueue.pop();

        // skip all inactive events (as the purpose of
        // nextEventFromQueue() is to activate the next
        // event, and events which return false on
        // isCharged() will never be activated by the
        // EventQueue)
        if(pEvent->isCharged())
            return rEventQueue.addEvent( pEvent );
    }
    return false; // no more (active) events in queue
}

/** @return at least one event has been posted
 */
template <typename ContainerT>
bool fireAllEvents( ContainerT & rQueue, EventQueue & rEventQueue )
{
    bool bFiredAny = false;
    while (fireSingleEvent( rQueue, rEventQueue ))
        bFiredAny = true;
    return bFiredAny;
}

class EventContainer
{
public:
    EventContainer() :
        maEvents()
    {}

    void clearContainer()
    {
        maEvents = ImpEventQueue();
    }

    void addEvent( const EventSharedPtr& rEvent )
    {
        maEvents.push( rEvent );
    }

    bool isEmpty()
    {
        return maEvents.empty();
    }

protected:
    ImpEventQueue maEvents;
};

} // anon namespace

class PlainEventHandler : public EventHandler,
                          public EventContainer
{
public:
    PlainEventHandler( EventQueue & rEventQueue )
        : EventContainer(), mrEventQueue(rEventQueue) {}

    virtual void dispose()
    {
        clearContainer();
    }

    virtual bool handleEvent()
    {
        return fireAllEvents( maEvents, mrEventQueue );
    }

private:
    EventQueue & mrEventQueue;
};

class AllAnimationEventHandler : public AnimationEventHandler
{
public:
    AllAnimationEventHandler( EventQueue& rEventQueue ) :
        mrEventQueue( rEventQueue ),
        maAnimationEventMap()
    {}

    virtual void dispose()
    {
        maAnimationEventMap.clear();
    }

    virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
    {
        ENSURE_OR_RETURN_FALSE(
            rNode,
            "AllAnimationEventHandler::handleAnimationEvent(): Invalid node" );

        bool bRet( false );

        ImpAnimationEventMap::iterator aIter;
        if( (aIter=maAnimationEventMap.find(
                 rNode->getXAnimationNode() )) != maAnimationEventMap.end() )
        {
            ImpEventVector& rVec( aIter->second );

            bRet = !rVec.empty();

            // registered node found -> fire all events in the vector
            std::for_each( rVec.begin(), rVec.end(),
                           boost::bind( &EventQueue::addEvent,
                                        boost::ref( mrEventQueue ), _1 ) );

            rVec.clear();
        }

        return bRet;
    }

    void addEvent( const EventSharedPtr&                                rEvent,
                   const uno::Reference< animations::XAnimationNode >&  xNode )
    {
        ImpAnimationEventMap::iterator aIter;
        if( (aIter=maAnimationEventMap.find( xNode )) ==
            maAnimationEventMap.end() )
        {
            // no entry for this animation -> create one
            aIter = maAnimationEventMap.insert(
                ImpAnimationEventMap::value_type( xNode,
                                                  ImpEventVector() ) ).first;
        }

        // add new event to queue
        aIter->second.push_back( rEvent );
    }

    bool isEmpty()
    {
        // find at least one animation with a non-empty vector
        ImpAnimationEventMap::const_iterator aCurr( maAnimationEventMap.begin() );
        const ImpAnimationEventMap::const_iterator aEnd( maAnimationEventMap.end() );
        while( aCurr != aEnd )
        {
            if( !aCurr->second.empty() )
                return false; // at least one non-empty entry found

            ++aCurr;
        }

        return true; // not a single non-empty entry found
    }

private:
    EventQueue&             mrEventQueue;
    ImpAnimationEventMap    maAnimationEventMap;
};

class ClickEventHandler : public MouseEventHandler_,
                          public EventHandler,
                          public EventContainer
{
public:
    ClickEventHandler( EventQueue& rEventQueue ) :
        EventContainer(),
        mrEventQueue( rEventQueue ),
        mbAdvanceOnClick( true )
    {}

    void setAdvanceOnClick( bool bAdvanceOnClick )
    {
        mbAdvanceOnClick = bAdvanceOnClick;
    }

private:
    virtual void dispose()
    {
        clearContainer();
    }

    // triggered by API calls, e.g. space bar
    virtual bool handleEvent()
    {
        return handleEvent_impl();
    }

    // triggered by mouse release:
    virtual bool handleMouseReleased( const awt::MouseEvent& evt )
    {
        if(evt.Buttons != awt::MouseButton::LEFT)
            return false;

        if( mbAdvanceOnClick ) {
            // fire next event
            return handleEvent_impl();
        }
        else {
            return false; // advance-on-click disabled
        }
    }

    // triggered by both:
    virtual bool handleEvent_impl()
    {
        // fire next event:
        return fireSingleEvent( maEvents, mrEventQueue );
    }

private:
    EventQueue& mrEventQueue;
    bool        mbAdvanceOnClick;
};

class SkipEffectEventHandler : public ClickEventHandler
{
public:
    SkipEffectEventHandler( EventQueue & rEventQueue,
                            EventMultiplexer & rEventMultiplexer )
        : ClickEventHandler(rEventQueue),
          mrEventQueue(rEventQueue),
          mrEventMultiplexer(rEventMultiplexer),
          mbSkipTriggersNextEffect(true) {}

    /** Remember to trigger (or not to trigger) the next effect after the
        current effect is skipped.
    */
    void setSkipTriggersNextEffect (const bool bSkipTriggersNextEffect)
    { mbSkipTriggersNextEffect = bSkipTriggersNextEffect; }

    ///  Skip the current effect but do not triggere the next effect.
    void skipEffect (void) { handleEvent_impl(false); }

private:
    virtual bool handleEvent_impl()
    {
        return handleEvent_impl(true);
    }

    bool handleEvent_impl (bool bNotifyNextEffect)
    {
        // fire all events, so animation nodes can register their
        // next effect listeners:
        if(fireAllEvents( maEvents, mrEventQueue ))
        {
            if (mbSkipTriggersNextEffect && bNotifyNextEffect)
            {
                // then simulate a next effect event: this skip effect
                // handler is triggered upon next effect events (multiplexer
                // prio=-1)!  Posting a notifyNextEffect() here is only safe
                // (we don't run into busy loop), because we assume that
                // someone has registered above for next effects
                // (multiplexer prio=0) at the user event queue.
                return mrEventQueue.addEventWhenQueueIsEmpty(
                    makeEvent( boost::bind( &EventMultiplexer::notifyNextEffect,
                                            boost::ref(mrEventMultiplexer) ),
                               "EventMultiplexer::notifyNextEffect") );
            }
            else
                return true;
        }
        return false;
    }

private:
    EventQueue & mrEventQueue;
    EventMultiplexer & mrEventMultiplexer;
    bool mbSkipTriggersNextEffect;
};

class RewindEffectEventHandler : public MouseEventHandler_,
                                 public EventContainer
{
public:
    RewindEffectEventHandler( EventQueue & rEventQueue )
        : EventContainer(), mrEventQueue(rEventQueue) {}

private:
    virtual void dispose()
    {
        clearContainer();
    }

    virtual bool handleMouseReleased( awt::MouseEvent const& evt )
    {
        if(evt.Buttons != awt::MouseButton::RIGHT)
            return false;

        return fireAllEvents( maEvents, mrEventQueue );
    }

private:
    EventQueue & mrEventQueue;
};

/** Base class to share some common code between
    ShapeClickEventHandler and MouseMoveHandler

    @derive override necessary MouseEventHandler interface methods,
    call sendEvent() method to actually process the event.
*/
class MouseHandlerBase : public MouseEventHandler_
{
public:
    MouseHandlerBase( EventQueue& rEventQueue ) :
        mrEventQueue( rEventQueue ),
        maShapeEventMap()
    {}

    virtual void dispose()
    {
        // TODO(Q1): Check whether plain vector with swap idiom is
        // okay here
        maShapeEventMap = ImpShapeEventMap();
    }

    void addEvent( const EventSharedPtr& rEvent,
                   const ShapeSharedPtr& rShape )
    {
        ImpShapeEventMap::iterator aIter;
        if( (aIter=maShapeEventMap.find( rShape )) == maShapeEventMap.end() )
        {
            // no entry for this shape -> create one
            aIter = maShapeEventMap.insert(
                ImpShapeEventMap::value_type( rShape,
                                              ImpEventQueue() ) ).first;
        }

        // add new event to queue
        aIter->second.push( rEvent );
    }

    bool isEmpty()
    {
        // find at least one shape with a non-empty queue
        ImpShapeEventMap::reverse_iterator aCurrShape( maShapeEventMap.begin());
        ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.end() );
        while( aCurrShape != aEndShape )
        {
            if( !aCurrShape->second.empty() )
                return false; // at least one non-empty entry found

            ++aCurrShape;
        }

        return true; // not a single non-empty entry found
    }

protected:
    bool hitTest( const awt::MouseEvent&                e,
                  ImpShapeEventMap::reverse_iterator&   o_rHitShape )
    {
        // find hit shape in map
        const basegfx::B2DPoint aPosition( e.X, e.Y );

        // find matching shape (scan reversely, to coarsely match
        // paint order)
        ImpShapeEventMap::reverse_iterator       aCurrShape(maShapeEventMap.rbegin());
        const ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.rend() );
        while( aCurrShape != aEndShape )
        {
            // TODO(F2): Get proper geometry polygon from the
            // shape, to avoid having areas outside the shape
            // react on the mouse
            if( aCurrShape->first->getBounds().isInside( aPosition ) &&
                aCurrShape->first->isVisible() )
            {
                // shape hit, and shape is visible - report a
                // hit
                o_rHitShape = aCurrShape;
                return true;
            }

            ++aCurrShape;
        }

        return false; // nothing hit
    }

    bool sendEvent( ImpShapeEventMap::reverse_iterator& io_rHitShape )
    {
        // take next event from queue
        const bool bRet( fireSingleEvent( io_rHitShape->second,
                                          mrEventQueue ) );

        // clear shape entry, if its queue is
        // empty. This is important, since the shapes
        // are held by shared ptr, and might otherwise
        // not get released, even after their owning
        // slide is long gone.
        if( io_rHitShape->second.empty() )
        {
            // this looks funny, since ::std::map does
            // provide an erase( iterator )
            // method. Unfortunately, stlport does not
            // declare the obvious erase(
            // reverse_iterator ) needed here (missing
            // orthogonality, eh?)
            maShapeEventMap.erase( io_rHitShape->first );
        }

        return bRet;
    }

    bool processEvent( const awt::MouseEvent& e )
    {
        ImpShapeEventMap::reverse_iterator aCurrShape;

        if( hitTest( e, aCurrShape ) )
            return sendEvent( aCurrShape );

        return false; // did not handle the event
    }

private:
    EventQueue&         mrEventQueue;
    ImpShapeEventMap    maShapeEventMap;
};

class ShapeClickEventHandler : public MouseHandlerBase
{
public:
    ShapeClickEventHandler( CursorManager& rCursorManager,
                            EventQueue&    rEventQueue ) :
        MouseHandlerBase( rEventQueue ),
        mrCursorManager( rCursorManager )
    {}

    virtual bool handleMouseReleased( const awt::MouseEvent& e )
    {
        if(e.Buttons != awt::MouseButton::LEFT)
            return false;
        return processEvent( e );
    }

    virtual bool handleMouseMoved( const awt::MouseEvent& e )
    {
        // TODO(P2): Maybe buffer last shape touched

        // if we have a shape click event, and the mouse
        // hovers over this shape, change cursor to hand
        ImpShapeEventMap::reverse_iterator aDummy;
        if( hitTest( e, aDummy ) )
            mrCursorManager.requestCursor( awt::SystemPointer::REFHAND );

        return false; // we don't /eat/ this event. Lower prio
        // handler should see it, too.
    }

private:
    CursorManager& mrCursorManager;
};

class MouseEnterHandler : public MouseHandlerBase
{
public:
    MouseEnterHandler( EventQueue& rEventQueue )
        : MouseHandlerBase( rEventQueue ),
          mpLastShape() {}

    virtual bool handleMouseMoved( const awt::MouseEvent& e )
    {
        // TODO(P2): Maybe buffer last shape touched, and
        // check against that _first_

        ImpShapeEventMap::reverse_iterator aCurr;
        if( hitTest( e, aCurr ) )
        {
            if( aCurr->first != mpLastShape )
            {
                // we actually hit a shape, and it's different
                // from the previous one - thus we just
                // entered it, raise event
                sendEvent( aCurr );
                mpLastShape = aCurr->first;
            }
        }
        else
        {
            // don't hit no shape - thus, last shape is NULL
            mpLastShape.reset();
        }

        return false; // we don't /eat/ this event. Lower prio
        // handler should see it, too.
    }

private:
    ShapeSharedPtr mpLastShape;
};

class MouseLeaveHandler : public MouseHandlerBase
{
public:
    MouseLeaveHandler( EventQueue& rEventQueue )
        : MouseHandlerBase( rEventQueue ),
          maLastIter() {}

    virtual bool handleMouseMoved( const awt::MouseEvent& e )
    {
        // TODO(P2): Maybe buffer last shape touched, and
        // check against that _first_

        ImpShapeEventMap::reverse_iterator aCurr;
        if( hitTest( e, aCurr ) )
        {
            maLastIter = aCurr;
        }
        else
        {
            if( maLastIter->first )
            {
                // last time, we were over a shape, now we're
                // not - we thus just left that shape, raise
                // event
                sendEvent( maLastIter );
            }

            // in any case, when we hit this else-branch: no
            // shape hit, thus have to clear maLastIter
            maLastIter = ImpShapeEventMap::reverse_iterator();
        }

        return false; // we don't /eat/ this event. Lower prio
        // handler should see it, too.
    }

private:
    ImpShapeEventMap::reverse_iterator maLastIter;
};

template< typename Handler, typename Functor >
void UserEventQueue::registerEvent(
    boost::shared_ptr< Handler >& rHandler,
    const EventSharedPtr&         rEvent,
    const Functor&                rRegistrationFunctor )
{
    ENSURE_OR_THROW( rEvent,
                      "UserEventQueue::registerEvent(): Invalid event" );

    if( !rHandler ) {
        // create handler
        rHandler.reset( new Handler( mrEventQueue ) );
        // register handler on EventMultiplexer
        rRegistrationFunctor( rHandler );
    }

    rHandler->addEvent( rEvent );
}

template< typename Handler, typename Arg, typename Functor >
void UserEventQueue::registerEvent(
    boost::shared_ptr< Handler >& rHandler,
    const EventSharedPtr&         rEvent,
    const Arg&                    rArg,
    const Functor&                rRegistrationFunctor )
{
    ENSURE_OR_THROW( rEvent,
                      "UserEventQueue::registerEvent(): Invalid event" );

    if( !rHandler ) {
        // create handler
        rHandler.reset( new Handler( mrEventQueue ) );

        // register handler on EventMultiplexer
        rRegistrationFunctor( rHandler );
    }

    rHandler->addEvent( rEvent, rArg );
}


// Public methods
// =====================================================

UserEventQueue::UserEventQueue( EventMultiplexer&   rMultiplexer,
                                EventQueue&         rEventQueue,
                                CursorManager&      rCursorManager )
    : mrMultiplexer( rMultiplexer ),
      mrEventQueue( rEventQueue ),
      mrCursorManager( rCursorManager ),
      mpStartEventHandler(),
      mpEndEventHandler(),
      mpAnimationStartEventHandler(),
      mpAnimationEndEventHandler(),
      mpAudioStoppedEventHandler(),
      mpClickEventHandler(),
      mpSkipEffectEventHandler(),
      mpRewindEffectEventHandler(),
      mpDoubleClickEventHandler(),
      mpMouseEnterHandler(),
      mpMouseLeaveHandler(),
      mbAdvanceOnClick( true )
{
}

UserEventQueue::~UserEventQueue()
{
    try
    {
        // unregister all handlers
        clear();
    }
    catch (uno::Exception &) {
        OSL_ENSURE( false, rtl::OUStringToOString(
                        comphelper::anyToString(
                            cppu::getCaughtException() ),
                        RTL_TEXTENCODING_UTF8 ).getStr() );
    }
}

bool UserEventQueue::isEmpty() const
{
    // TODO(T2): This is not thread safe, the handlers are all
    // only separately synchronized. This poses the danger of
    // generating false empty status on XSlideShow::update(), such
    // that the last events of a slide are not triggered.

    // we're empty iff all handler queues are empty
    return
        (mpStartEventHandler ? mpStartEventHandler->isEmpty() : true) &&
        (mpEndEventHandler ? mpEndEventHandler->isEmpty() : true) &&
        (mpAnimationStartEventHandler ? mpAnimationStartEventHandler->isEmpty() : true) &&
        (mpAnimationEndEventHandler ? mpAnimationEndEventHandler->isEmpty() : true) &&
        (mpAudioStoppedEventHandler ? mpAudioStoppedEventHandler->isEmpty() : true) &&
        (mpShapeClickEventHandler ? mpShapeClickEventHandler->isEmpty() : true) &&
        (mpClickEventHandler ? mpClickEventHandler->isEmpty() : true) &&
        (mpSkipEffectEventHandler ? mpSkipEffectEventHandler->isEmpty() : true) &&
        (mpRewindEffectEventHandler ? mpRewindEffectEventHandler->isEmpty() : true) &&
        (mpShapeDoubleClickEventHandler ? mpShapeDoubleClickEventHandler->isEmpty() : true) &&
        (mpDoubleClickEventHandler ? mpDoubleClickEventHandler->isEmpty() : true) &&
        (mpMouseEnterHandler ? mpMouseEnterHandler->isEmpty() : true) &&
        (mpMouseLeaveHandler ? mpMouseLeaveHandler->isEmpty() : true);
}

void UserEventQueue::clear()
{
    // unregister and delete all handlers
    if( mpStartEventHandler ) {
        mrMultiplexer.removeSlideStartHandler( mpStartEventHandler );
        mpStartEventHandler.reset();
    }
    if( mpEndEventHandler ) {
        mrMultiplexer.removeSlideEndHandler( mpEndEventHandler );
        mpEndEventHandler.reset();
    }
    if( mpAnimationStartEventHandler ) {
        mrMultiplexer.removeAnimationStartHandler(
            mpAnimationStartEventHandler );
        mpAnimationStartEventHandler.reset();
    }
    if( mpAnimationEndEventHandler ) {
        mrMultiplexer.removeAnimationEndHandler( mpAnimationEndEventHandler );
        mpAnimationEndEventHandler.reset();
    }
    if( mpAudioStoppedEventHandler ) {
        mrMultiplexer.removeAudioStoppedHandler( mpAudioStoppedEventHandler );
        mpAudioStoppedEventHandler.reset();
    }
    if( mpShapeClickEventHandler ) {
        mrMultiplexer.removeClickHandler( mpShapeClickEventHandler );
        mrMultiplexer.removeMouseMoveHandler( mpShapeClickEventHandler );
        mpShapeClickEventHandler.reset();
    }
    if( mpClickEventHandler ) {
        mrMultiplexer.removeClickHandler( mpClickEventHandler );
        mrMultiplexer.removeNextEffectHandler( mpClickEventHandler );
        mpClickEventHandler.reset();
    }
    if(mpSkipEffectEventHandler) {
        mrMultiplexer.removeClickHandler( mpSkipEffectEventHandler );
        mrMultiplexer.removeNextEffectHandler( mpSkipEffectEventHandler );
        mpSkipEffectEventHandler.reset();
    }
    if(mpRewindEffectEventHandler) {
        mrMultiplexer.removeClickHandler( mpRewindEffectEventHandler );
        mpRewindEffectEventHandler.reset();
    }
    if( mpShapeDoubleClickEventHandler ) {
        mrMultiplexer.removeDoubleClickHandler( mpShapeDoubleClickEventHandler );
        mrMultiplexer.removeMouseMoveHandler( mpShapeDoubleClickEventHandler );
        mpShapeDoubleClickEventHandler.reset();
    }
    if( mpDoubleClickEventHandler ) {
        mrMultiplexer.removeDoubleClickHandler( mpDoubleClickEventHandler );
        mpDoubleClickEventHandler.reset();
    }
    if( mpMouseEnterHandler ) {
        mrMultiplexer.removeMouseMoveHandler( mpMouseEnterHandler );
        mpMouseEnterHandler.reset();
    }
    if( mpMouseLeaveHandler ) {
        mrMultiplexer.removeMouseMoveHandler( mpMouseLeaveHandler );
        mpMouseLeaveHandler.reset();
    }
}

void UserEventQueue::setAdvanceOnClick( bool bAdvanceOnClick )
{
    mbAdvanceOnClick = bAdvanceOnClick;

    // forward to handler, if existing. Otherwise, the handler
    // creation will do the forwarding.
    if( mpClickEventHandler )
        mpClickEventHandler->setAdvanceOnClick( bAdvanceOnClick );
}


void UserEventQueue::registerSlideStartEvent( const EventSharedPtr& rEvent )
{
    registerEvent( mpStartEventHandler,
                   rEvent,
                   boost::bind( &EventMultiplexer::addSlideStartHandler,
                                boost::ref( mrMultiplexer ), _1 ) );
}

void UserEventQueue::registerSlideEndEvent( const EventSharedPtr& rEvent )
{
    registerEvent( mpEndEventHandler,
                   rEvent,
                   boost::bind( &EventMultiplexer::addSlideEndHandler,
                                boost::ref( mrMultiplexer ), _1 ) );
}

void UserEventQueue::registerAnimationStartEvent(
    const EventSharedPtr&                                 rEvent,
    const uno::Reference< animations::XAnimationNode>&    xNode )
{
    registerEvent( mpAnimationStartEventHandler,
                   rEvent,
                   xNode,
                   boost::bind( &EventMultiplexer::addAnimationStartHandler,
                                boost::ref( mrMultiplexer ), _1 ) );
}

void UserEventQueue::registerAnimationEndEvent(
    const EventSharedPtr&                               rEvent,
    const uno::Reference<animations::XAnimationNode>&   xNode )
{
    registerEvent( mpAnimationEndEventHandler,
                   rEvent,
                   xNode,
                   boost::bind( &EventMultiplexer::addAnimationEndHandler,
                                boost::ref( mrMultiplexer ), _1 ) );
}

void UserEventQueue::registerAudioStoppedEvent(
    const EventSharedPtr&                               rEvent,
    const uno::Reference<animations::XAnimationNode>&   xNode )
{
    registerEvent( mpAudioStoppedEventHandler,
                   rEvent,
                   xNode,
                   boost::bind( &EventMultiplexer::addAudioStoppedHandler,
                                boost::ref( mrMultiplexer ), _1 ) );
}

void UserEventQueue::registerShapeClickEvent( const EventSharedPtr& rEvent,
                                              const ShapeSharedPtr& rShape )
{
    ENSURE_OR_THROW(
        rEvent,
        "UserEventQueue::registerShapeClickEvent(): Invalid event" );

    if( !mpShapeClickEventHandler )
    {
        // create handler
        mpShapeClickEventHandler.reset(
            new ShapeClickEventHandler(mrCursorManager,
                                       mrEventQueue) );

        // register handler on EventMultiplexer
        mrMultiplexer.addClickHandler( mpShapeClickEventHandler, 1.0 );
        mrMultiplexer.addMouseMoveHandler( mpShapeClickEventHandler, 1.0 );
    }

    mpShapeClickEventHandler->addEvent( rEvent, rShape );
}

namespace {
class ClickEventRegistrationFunctor
{
public:
    ClickEventRegistrationFunctor( EventMultiplexer& rMultiplexer,
                                   double            nPrio,
                                   bool              bAdvanceOnClick )
        : mrMultiplexer( rMultiplexer ),
          mnPrio(nPrio),
          mbAdvanceOnClick( bAdvanceOnClick ) {}

    void operator()( const boost::shared_ptr<ClickEventHandler>& rHandler )const
    {
        // register the handler on _two_ sources: we want the
        // nextEffect events, e.g. space bar, to trigger clicks, as well!
        mrMultiplexer.addClickHandler( rHandler, mnPrio );
        mrMultiplexer.addNextEffectHandler( rHandler, mnPrio );

        // forward advance-on-click state to newly
        // generated handler (that's the only reason why
        // we're called here)
        rHandler->setAdvanceOnClick( mbAdvanceOnClick );
    }

private:
    EventMultiplexer&   mrMultiplexer;
    double const        mnPrio;
    bool const          mbAdvanceOnClick;
};
} // anon namespace

void UserEventQueue::registerNextEffectEvent( const EventSharedPtr& rEvent )
{
    // TODO: better name may be mpNextEffectEventHandler?  then we have
    //       next effect (=> waiting to be started)
    //       skip effect (skipping the currently running one)
    //       rewind effect (rewinding back running one and waiting (again)
    //                      to be started)
    registerEvent( mpClickEventHandler,
                   rEvent,
                   ClickEventRegistrationFunctor( mrMultiplexer,
                                                  0.0 /* default prio */,
                                                  mbAdvanceOnClick ) );
}

void UserEventQueue::registerSkipEffectEvent(
    EventSharedPtr const & pEvent,
    const bool bSkipTriggersNextEffect)
{
    if(!mpSkipEffectEventHandler)
    {
        mpSkipEffectEventHandler.reset(
            new SkipEffectEventHandler( mrEventQueue, mrMultiplexer ) );
        // register the handler on _two_ sources: we want the
        // nextEffect events, e.g. space bar, to trigger clicks, as well!
        mrMultiplexer.addClickHandler( mpSkipEffectEventHandler,
                                       -1.0 /* prio below default */ );
        mrMultiplexer.addNextEffectHandler( mpSkipEffectEventHandler,
                                            -1.0 /* prio below default */ );
        // forward advance-on-click state to newly
        // generated handler (that's the only reason why
        // we're called here)
        mpSkipEffectEventHandler->setAdvanceOnClick( mbAdvanceOnClick );
    }
    mpSkipEffectEventHandler->setSkipTriggersNextEffect(bSkipTriggersNextEffect);
    mpSkipEffectEventHandler->addEvent( pEvent );
}

void UserEventQueue::registerRewindEffectEvent( EventSharedPtr const& pEvent )
{
    registerEvent( mpRewindEffectEventHandler,
                   pEvent,
                   boost::bind( &EventMultiplexer::addClickHandler,
                                boost::ref(mrMultiplexer), _1,
                                -1.0 /* prio below default */ ) );
}

void UserEventQueue::registerShapeDoubleClickEvent(
    const EventSharedPtr& rEvent,
    const ShapeSharedPtr& rShape )
{
    ENSURE_OR_THROW(
        rEvent,
        "UserEventQueue::registerShapeDoubleClickEvent(): Invalid event" );

    if( !mpShapeDoubleClickEventHandler )
    {
        // create handler
        mpShapeDoubleClickEventHandler.reset(
            new ShapeClickEventHandler(mrCursorManager,
                                       mrEventQueue) );

        // register handler on EventMultiplexer
        mrMultiplexer.addDoubleClickHandler( mpShapeDoubleClickEventHandler,
                                             1.0 );
        mrMultiplexer.addMouseMoveHandler( mpShapeDoubleClickEventHandler,
                                           1.0 );
    }

    mpShapeDoubleClickEventHandler->addEvent( rEvent, rShape );
}

void UserEventQueue::registerDoubleClickEvent( const EventSharedPtr& rEvent )
{
    registerEvent( mpDoubleClickEventHandler,
                   rEvent,
                   boost::bind( &EventMultiplexer::addDoubleClickHandler,
                                boost::ref( mrMultiplexer ), _1,
                                0.0 /* default prio */ ) );
}

void UserEventQueue::registerMouseEnterEvent( const EventSharedPtr& rEvent,
                                              const ShapeSharedPtr& rShape )
{
    registerEvent( mpMouseEnterHandler,
                   rEvent,
                   rShape,
                   boost::bind( &EventMultiplexer::addMouseMoveHandler,
                                boost::ref( mrMultiplexer ), _1,
                                0.0 /* default prio */ ) );
}

void UserEventQueue::registerMouseLeaveEvent( const EventSharedPtr& rEvent,
                                              const ShapeSharedPtr& rShape )
{
    registerEvent( mpMouseLeaveHandler,
                   rEvent,
                   rShape,
                   boost::bind( &EventMultiplexer::addMouseMoveHandler,
                                boost::ref( mrMultiplexer ), _1,
                                0.0 /* default prio */ ) );
}

void UserEventQueue::callSkipEffectEventHandler (void)
{
    ::boost::shared_ptr<SkipEffectEventHandler> pHandler (
        ::boost::dynamic_pointer_cast<SkipEffectEventHandler>(mpSkipEffectEventHandler));
    if (pHandler)
        pHandler->skipEffect();
}

} // namespace internal
} // namespace presentation
