/**************************************************************
 * 
 * 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 <canvas/verbosetrace.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <comphelper/anytostring.hxx>
#include <com/sun/star/presentation/ParagraphTarget.hpp>
#include <com/sun/star/animations/Timing.hpp>
#include <com/sun/star/animations/AnimationAdditiveMode.hpp>
#include <com/sun/star/presentation/ShapeAnimationSubType.hpp>

#include "nodetools.hxx"
#include "doctreenode.hxx"
#include "animationbasenode.hxx"
#include "delayevent.hxx"
#include "framerate.hxx"

#include <boost/bind.hpp>
#include <boost/optional.hpp>
#include <algorithm>

using namespace com::sun::star;

namespace slideshow {
namespace internal {

AnimationBaseNode::AnimationBaseNode(
    const uno::Reference< animations::XAnimationNode >&   xNode, 
    const BaseContainerNodeSharedPtr&                     rParent,
    const NodeContext&                                    rContext )
    : BaseNode( xNode, rParent, rContext ),
      mxAnimateNode( xNode, uno::UNO_QUERY_THROW ),
      maAttributeLayerHolder(),
      maSlideSize( rContext.maSlideSize ),
      mpActivity(),
      mpShape(),
      mpShapeSubset(),
      mpSubsetManager(rContext.maContext.mpSubsettableShapeManager),
      mbIsIndependentSubset( rContext.mbIsIndependentSubset )
{
    // extract native node targets
    // ===========================
    
    // plain shape target
    uno::Reference< drawing::XShape > xShape( mxAnimateNode->getTarget(),
                                              uno::UNO_QUERY );
    
    // distinguish 5 cases:
    // 
    //  - plain shape target
    //  (NodeContext.mpMasterShapeSubset full set)
    //
    //  - parent-generated subset (generate an
    //  independent subset)
    //
    //  - parent-generated subset from iteration
    //  (generate a dependent subset)
    //
    //  - XShape target at the XAnimatioNode (generate
    //  a plain shape target)
    //
    //  - ParagraphTarget target at the XAnimationNode
    //  (generate an independent shape subset)
    if( rContext.mpMasterShapeSubset )
    {
        if( rContext.mpMasterShapeSubset->isFullSet() )
        {
            // case 1: plain shape target from parent
            mpShape = rContext.mpMasterShapeSubset->getSubsetShape();
        }
        else
        {
            // cases 2 & 3: subset shape 
            mpShapeSubset = rContext.mpMasterShapeSubset;
        }
    }
    else
    {
        // no parent-provided shape, try to extract
        // from XAnimationNode - cases 4 and 5
        
        if( xShape.is() )
        { 
            mpShape = lookupAttributableShape( getContext().mpSubsettableShapeManager,
                                               xShape );
        }
        else
        {
            // no shape provided. Maybe a ParagraphTarget?
            presentation::ParagraphTarget aTarget;
            
            if( !(mxAnimateNode->getTarget() >>= aTarget) )
                ENSURE_OR_THROW(
                    false, "could not extract any target information" );
            
            xShape = aTarget.Shape;
            
            ENSURE_OR_THROW( xShape.is(), "invalid shape in ParagraphTarget" );
            
            mpShape = lookupAttributableShape( getContext().mpSubsettableShapeManager,
                                               xShape );
            
            // NOTE: For shapes with ParagraphTarget, we ignore
            // the SubItem property. We implicitely assume that it
            // is set to ONLY_TEXT.
            OSL_ENSURE(
                mxAnimateNode->getSubItem() ==
                presentation::ShapeAnimationSubType::ONLY_TEXT ||
                mxAnimateNode->getSubItem() ==
                presentation::ShapeAnimationSubType::AS_WHOLE,
                "ParagraphTarget given, but subitem not AS_TEXT or AS_WHOLE? "
                "Make up your mind, I'll ignore the subitem." );
            
            // okay, found a ParagraphTarget with a valid XShape. Does the shape
            // provide the given paragraph?
            const DocTreeNode& rTreeNode( 
                mpShape->getTreeNodeSupplier().getTreeNode(
                    aTarget.Paragraph, 
                    DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ) );
            
            // CAUTION: the creation of the subset shape
            // _must_ stay in the node constructor, since
            // Slide::prefetchShow() initializes shape
            // attributes right after animation import (or
            // the Slide class must be changed).
            mpShapeSubset.reset(
                new ShapeSubset( mpShape,
                                 rTreeNode,
                                 mpSubsetManager ));
            
            // Override NodeContext, and flag this node as
            // a special independent subset one. This is
            // important when applying initial attributes:
            // independent shape subsets must be setup
            // when the slide starts, since they, as their
            // name suggest, can have state independent to
            // the master shape. The following example
            // might illustrate that: a master shape has
            // no effect, one of the text paragraphs
            // within it has an appear effect. Now, the
            // respective paragraph must be invisible when
            // the slide is initially shown, and become
            // visible only when the effect starts.
            mbIsIndependentSubset = true;
            
            // already enable subset right here, the
            // setup of initial shape attributes of
            // course needs the subset shape
            // generated, to apply e.g. visibility
            // changes.
            mpShapeSubset->enableSubsetShape();
        }
    }
}

void AnimationBaseNode::dispose()
{
    if (mpActivity) {
        mpActivity->dispose();
        mpActivity.reset();
    }
    
    maAttributeLayerHolder.reset();
    mxAnimateNode.clear();
    mpShape.reset();
    mpShapeSubset.reset();
    
    BaseNode::dispose();
}

bool AnimationBaseNode::init_st()
{
    // if we've still got an old activity lying around, dispose it:
    if (mpActivity) {
        mpActivity->dispose();
        mpActivity.reset();
    }
    
    // note: actually disposing the activity too early might cause problems,
    // because on dequeued() it calls endAnimation(pAnim->end()), thus ending
    // animation _after_ last screen update.
    // review that end() is properly called (which calls endAnimation(), too).
    
    try {
        // TODO(F2): For restart functionality, we must regenerate activities,
        // since they are not able to reset their state (or implement _that_)
        mpActivity = createActivity();
    }
    catch (uno::Exception const&) {
        OSL_ENSURE( false, rtl::OUStringToOString(
                        comphelper::anyToString(cppu::getCaughtException()),
                        RTL_TEXTENCODING_UTF8 ) );
        // catch and ignore. We later handle empty activities, but for 
        // other nodes to function properly, the core functionality of
        // this node must remain up and running.
    }
    return true;
}

bool AnimationBaseNode::resolve_st()
{    
    // enable shape subset for automatically generated
    // subsets. Independent subsets are already setup
    // during construction time. Doing it only here
    // saves us a lot of sprites and shapes lying
    // around. This is especially important for
    // character-wise iterations, since the shape
    // content (e.g. thousands of characters) would
    // otherwise be painted character-by-character.
    if (isDependentSubsettedShape() && mpShapeSubset) {
        mpShapeSubset->enableSubsetShape();
    }
    return true;
}

void AnimationBaseNode::activate_st()
{
    // create new attribute layer
    maAttributeLayerHolder.createAttributeLayer( getShape() );
    
    ENSURE_OR_THROW( maAttributeLayerHolder.get(),
                      "Could not generate shape attribute layer" );
    
    // TODO(Q2): This affects the way mpActivity
    // works, but is performed here because of
    // locality (we're fiddling with the additive mode
    // here, anyway, and it's the only place where we
    // do). OTOH, maybe the complete additive mode
    // setup should be moved to the activities.
    
    // for simple by-animations, the SMIL spec
    // requires us to emulate "0,by-value" value list
    // behaviour, with additive mode forced to "sum",
    // no matter what the input is
    // (http://www.w3.org/TR/smil20/animation.html#adef-by).
    if( mxAnimateNode->getBy().hasValue() &&
        !mxAnimateNode->getTo().hasValue() &&
        !mxAnimateNode->getFrom().hasValue() )
    {
        // force attribute mode to REPLACE (note the
        // subtle discrepancy to the paragraph above,
        // where SMIL requires SUM. This is internally
        // handled by the FromToByActivity, and is
        // because otherwise DOM values would not be
        // handled correctly: the activity cannot
        // determine whether an
        // Activity::getUnderlyingValue() yields the
        // DOM value, or already a summed-up conglomerate)
        // 
        // Note that this poses problems with our
        // hybrid activity duration (time or min number of frames),
        // since if activities
        // exceed their duration, wrong 'by' start
        // values might arise ('Laser effect')
        maAttributeLayerHolder.get()->setAdditiveMode(
            animations::AnimationAdditiveMode::REPLACE );
    }
    else
    {
        // apply additive mode to newly created Attribute layer
        maAttributeLayerHolder.get()->setAdditiveMode(
            mxAnimateNode->getAdditive() );
    }
    
    // fake normal animation behaviour, even if we
    // show nothing.  This is the appropriate way to
    // handle errors on Activity generation, because
    // maybe all other effects on the slide are
    // correctly initialized (but won't run, if we
    // signal an error here)
    if (mpActivity) {
        // supply Activity (and the underlying Animation) with
        // it's AttributeLayer, to perform the animation on
        mpActivity->setTargets( getShape(), maAttributeLayerHolder.get() );
        
        // add to activities queue
        getContext().mrActivitiesQueue.addActivity( mpActivity );
    }
    else {
        // Actually, DO generate the event for empty activity,
        // to keep the chain of animations running
        BaseNode::scheduleDeactivationEvent();
    }
}

void AnimationBaseNode::deactivate_st( NodeState eDestState )
{
    if (eDestState == FROZEN) {
        if (mpActivity)
            mpActivity->end();
    }
    
    if (isDependentSubsettedShape()) {
        // for dependent subsets, remove subset shape
        // from layer, re-integrate subsetted part
        // back into original shape. For independent
        // subsets, we cannot make any assumptions
        // about subset attribute state relative to
        // master shape, thus, have to keep it. This
        // will effectively re-integrate the subsetted
        // part into the original shape (whose
        // animation will hopefully have ended, too)
        
        // this statement will save a whole lot of
        // sprites for iterated text effects, since
        // those sprites will only exist during the
        // actual lifetime of the effects
        if (mpShapeSubset) {
            mpShapeSubset->disableSubsetShape();
        }
    }
    
    if (eDestState == ENDED) {
        
        // no shape anymore, no layer needed:
        maAttributeLayerHolder.reset();
        
        if (! isDependentSubsettedShape()) {
            
            // for all other shapes, removing the
            // attribute layer quite possibly changes
            // shape display. Thus, force update
            AttributableShapeSharedPtr const pShape( getShape() );
            
            // don't anybody dare to check against
            // pShape->isVisible() here, removing the
            // attribute layer might actually make the
            // shape invisible!
            getContext().mpSubsettableShapeManager->notifyShapeUpdate( pShape );
        }
        
        if (mpActivity) {
            // kill activity, if still running
            mpActivity->dispose();
            mpActivity.reset();
        }
    }
}

bool AnimationBaseNode::hasPendingAnimation() const
{
    // TODO(F1): This might not always be true. Are there 'inactive' 
    // animation nodes?
    return true;
}

#if defined(VERBOSE) && defined(DBG_UTIL)
void AnimationBaseNode::showState() const
{
    BaseNode::showState();
    
    VERBOSE_TRACE( "AnimationBaseNode info: independent subset=%s",
                   mbIsIndependentSubset ? "y" : "n" );
}
#endif

ActivitiesFactory::CommonParameters
AnimationBaseNode::fillCommonParameters() const
{
    double nDuration = 0.0;
    
    // TODO(F3): Duration/End handling is barely there
    if( !(mxAnimateNode->getDuration() >>= nDuration) ) {
        mxAnimateNode->getEnd() >>= nDuration; // Wah.
    }
    
    // minimal duration we fallback to (avoid 0 here!)
    nDuration = ::std::max( 0.001, nDuration );
    
    const bool bAutoReverse( mxAnimateNode->getAutoReverse() );
    
    boost::optional<double> aRepeats;
    double nRepeats = 0;
	bool bRepeatIndefinite = false;
    animations::Timing eTiming;

    // Search parent nodes for an explicitly stated repeat count.
    BaseNodeSharedPtr const pSelf( getSelf() );
    for ( boost::shared_ptr<BaseNode> pNode( pSelf );
          pNode;
          pNode = pNode->getParentNode() )
    {
        uno::Reference<animations::XAnimationNode> const xAnimationNode(
            pNode->getXAnimationNode() );
        if( (xAnimationNode->getRepeatCount() >>= nRepeats) )
        {
            // Found an explicit repeat count.
            break;
        }
        if( (xAnimationNode->getRepeatCount() >>= eTiming) &&
            (eTiming == animations::Timing_INDEFINITE ))
        {
            // Found an explicit repeat count of Timing::INDEFINITE.
            bRepeatIndefinite = true;
            break;
        }
    }

    if( nRepeats || bRepeatIndefinite ) {
        if (nRepeats)
        {
            aRepeats.reset( nRepeats );
        }
    }
    else {
        if( (mxAnimateNode->getRepeatDuration() >>= nRepeats) ) {
            // when repeatDuration is given,
            // autoreverse does _not_ modify the
            // active duration. Thus, calc repeat
            // count with already adapted simple
            // duration (twice the specified duration)
            
            // convert duration back to repeat counts
            if( bAutoReverse )
                aRepeats.reset( nRepeats / (2.0 * nDuration) );
            else
                aRepeats.reset( nRepeats / nDuration );
        }
        else {
            // no double value for both values - Timing::INDEFINITE?
            animations::Timing eTiming;
            
            if( !(mxAnimateNode->getRepeatDuration() >>= eTiming) ||
                eTiming != animations::Timing_INDEFINITE )
            {
                if( !(mxAnimateNode->getRepeatCount() >>= eTiming) ||
                    eTiming != animations::Timing_INDEFINITE )
                {
                    // no indefinite timing, no other values given -
                    // use simple run, i.e. repeat of 1.0
                    aRepeats.reset( 1.0 );
                }
            }
        }
    }

    // calc accel/decel:
    double nAcceleration = 0.0;
    double nDeceleration = 0.0;
    for ( boost::shared_ptr<BaseNode> pNode( pSelf );
          pNode; pNode = pNode->getParentNode() )
    {
        uno::Reference<animations::XAnimationNode> const xAnimationNode(
            pNode->getXAnimationNode() );
        nAcceleration = std::max( nAcceleration,
                                  xAnimationNode->getAcceleration() );
        nDeceleration = std::max( nDeceleration,
                                  xAnimationNode->getDecelerate() );
    }
    
    EventSharedPtr pEndEvent;
    if (pSelf) {
        pEndEvent = makeEvent(
            boost::bind( &AnimationNode::deactivate, pSelf ),
            "AnimationBaseNode::deactivate");
    }

    // Calculate the minimum frame count that depends on the duration and
    // the minimum frame count.
    const sal_Int32 nMinFrameCount (basegfx::clamp<sal_Int32>(
        basegfx::fround(nDuration * FrameRate::MinimumFramesPerSecond), 1, 10));

    return ActivitiesFactory::CommonParameters(
        pEndEvent,
        getContext().mrEventQueue,
        getContext().mrActivitiesQueue,
        nDuration,
        nMinFrameCount,
        bAutoReverse,
        aRepeats,
        nAcceleration,
        nDeceleration,
        getShape(),
        getSlideSize());
}

AttributableShapeSharedPtr AnimationBaseNode::getShape() const
{
    // any subsetting at all?
    if (mpShapeSubset)
        return mpShapeSubset->getSubsetShape();
    else
        return mpShape; // nope, plain shape always
}

} // namespace internal
} // namespace slideshow

