/**************************************************************
 * 
 * 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 skiped.
    */
    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 registerered 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

