/**************************************************************
 * 
 * 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 <com/sun/star/drawing/XShape.hpp>
#include <com/sun/star/animations/XAnimate.hpp>
#include <com/sun/star/animations/AnimationNodeType.hpp>
#include <com/sun/star/presentation/EffectNodeType.hpp>
#include <com/sun/star/presentation/TextAnimationType.hpp>
#include <com/sun/star/animations/XAnimateSet.hpp>
#include <com/sun/star/animations/XIterateContainer.hpp>
#include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
#include <com/sun/star/animations/XAnimateMotion.hpp>
#include <com/sun/star/animations/XAnimateColor.hpp>
#include <com/sun/star/animations/XAnimateTransform.hpp>
#include <com/sun/star/animations/AnimationTransformType.hpp>
#include <com/sun/star/animations/XTransitionFilter.hpp>
#include <com/sun/star/animations/XAudio.hpp>
#include <com/sun/star/presentation/ParagraphTarget.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <animations/animationnodehelper.hxx>
#include <basegfx/numeric/ftools.hxx>

#include "animationnodefactory.hxx"
#include "paralleltimecontainer.hxx"
#include "sequentialtimecontainer.hxx"
#include "propertyanimationnode.hxx"
#include "animationsetnode.hxx"
#include "animationpathmotionnode.hxx"
#include "animationcolornode.hxx"
#include "animationtransformnode.hxx"
#include "animationtransitionfilternode.hxx"
#include "animationaudionode.hxx"
#include "animationcommandnode.hxx"
#include "nodetools.hxx"
#include "tools.hxx"

#include <boost/bind.hpp>

using namespace ::com::sun::star;

namespace slideshow {
namespace internal {

namespace {

// forward declaration needed by NodeCreator
BaseNodeSharedPtr implCreateAnimationNode(
    const uno::Reference< animations::XAnimationNode >&  xNode,
    const BaseContainerNodeSharedPtr&                    rParent,
    const NodeContext&                                   rContext );

class NodeCreator
{
public:
    NodeCreator( BaseContainerNodeSharedPtr&    rParent,
                 const NodeContext&             rContext )
        : mrParent( rParent ), mrContext( rContext ) {}
    
    void operator()(
        const uno::Reference< animations::XAnimationNode >& xChildNode ) const
    {
        createChild( xChildNode, mrContext );
    }
    
protected:
    void createChild(
        const uno::Reference< animations::XAnimationNode >&   xChildNode,
        const NodeContext&                                    rContext ) const
    {
        BaseNodeSharedPtr pChild( implCreateAnimationNode( xChildNode,
                                                           mrParent,
                                                           rContext ) );
        
        OSL_ENSURE( pChild,
                    "NodeCreator::operator(): child creation failed" );
        
        // TODO(Q1): This yields circular references, which, it seems, is 
        // unavoidable here
        if( pChild )
            mrParent->appendChildNode( pChild );
    }
    
    BaseContainerNodeSharedPtr&     mrParent;
    const NodeContext&              mrContext;
};

/** Same as NodeCreator, only that NodeContext's
    SubsetShape is cloned for every child node.
    
    This is used for iterated animation node generation
*/
class CloningNodeCreator : private NodeCreator
{
public:
    CloningNodeCreator( BaseContainerNodeSharedPtr& rParent,
                        const NodeContext&          rContext )
        : NodeCreator( rParent, rContext ) {}
    
    void operator()(
        const uno::Reference< animations::XAnimationNode >& xChildNode ) const
    {
        NodeContext aContext( mrContext );
        
        // TODO(Q1): There's a catch here. If you clone a
        // subset whose actual subsetting has already been
        // realized (i.e. if enableSubsetShape() has been
        // called already), and the original of your clone
        // goes out of scope, then your subset will be
        // gone (SubsettableShapeManager::revokeSubset() be
        // called). As of now, this behaviour is not
        // triggered here (we either clone, XOR we enable
        // subset initially), but one might consider
        // reworking DrawShape/ShapeSubset to avoid this.
        
        // clone ShapeSubset, since each node needs their
        // own version of the ShapeSubset (otherwise,
        // e.g. activity counting does not work - subset
        // would be removed after first animation node
        // disables it). 
        //
        // NOTE: this is only a problem for animation
        // nodes that explicitely call
        // disableSubsetShape(). Independent shape subsets
        // (like those created for ParagraphTargets)
        // solely rely on the ShapeSubset destructor to
        // normalize things, which does the right thing
        // here: the subset is only removed after _the
        // last_ animation node releases the shared ptr.
        aContext.mpMasterShapeSubset.reset( 
            new ShapeSubset( *aContext.mpMasterShapeSubset ) );
        
        createChild( xChildNode, aContext );
    }
};

/** Create animation nodes for text iterations
    
    This method clones the animation nodes below xIterNode
    for every iterated shape entity.
*/
bool implCreateIteratedNodes(
    const uno::Reference< animations::XIterateContainer >&    xIterNode,
    BaseContainerNodeSharedPtr&                               rParent,
    const NodeContext&                                        rContext )
{
    ENSURE_OR_THROW( xIterNode.is(),
                      "implCreateIteratedNodes(): Invalid node" );
    
    const double nIntervalTimeout( xIterNode->getIterateInterval() );
    
    // valid iterate interval? We're ruling out monstrous
    // values here, to avoid pseudo 'hangs' in the
    // presentation
    if( nIntervalTimeout < 0.0 ||
        nIntervalTimeout > 1000.0 )
    {
        return false; // not an active iteration
    }
    
    if( ::basegfx::fTools::equalZero( nIntervalTimeout ) )
        OSL_TRACE( "implCreateIteratedNodes(): "
                   "iterate interval close to zero, there's "
                   "no point in defining such an effect "
                   "(visually equivalent to whole-shape effect)" );
    
    // Determine target shape (or subset)
    // ==================================
    
    // TODO(E1): I'm not too sure what to expect here...
    ENSURE_OR_RETURN_FALSE(
        xIterNode->getTarget().hasValue(),
        "implCreateIteratedNodes(): no target on ITERATE node" );
    
    uno::Reference< drawing::XShape > xTargetShape( xIterNode->getTarget(),
                                                    uno::UNO_QUERY );
    
    presentation::ParagraphTarget aTarget;
    sal_Int16                     nSubItem( xIterNode->getSubItem() );
    bool                          bParagraphTarget( false );
    
    if( !xTargetShape.is() )
    {
        // no shape provided. Maybe a ParagraphTarget?
        if( !(xIterNode->getTarget() >>= aTarget) )
            ENSURE_OR_RETURN_FALSE(
                false,
                "implCreateIteratedNodes(): could not extract any "
                "target information" );
        
        xTargetShape = aTarget.Shape;
        
        ENSURE_OR_RETURN_FALSE(
            xTargetShape.is(),
            "implCreateIteratedNodes(): invalid shape in ParagraphTarget" );
        
        // we've a paragraph target to iterate over, thus,
        // the whole animation container refers only to
        // the text
        nSubItem = presentation::ShapeAnimationSubType::ONLY_TEXT;
        
        bParagraphTarget = true;
    }
    
    // Lookup shape, and fill NodeContext
    // ==================================
    
    AttributableShapeSharedPtr  pTargetShape( 
        lookupAttributableShape( rContext.maContext.mpSubsettableShapeManager,
                                 xTargetShape ) );
    
    const DocTreeNodeSupplier& rTreeNodeSupplier(
        pTargetShape->getTreeNodeSupplier() );
    
    ShapeSubsetSharedPtr pTargetSubset;
    
    NodeContext aContext( rContext );
    
    // paragraph targets already need a subset as the
    // master shape (they're representing only a single
    // paragraph)
    if( bParagraphTarget )
    {
        ENSURE_OR_RETURN_FALSE( 
            aTarget.Paragraph >= 0 &&
            rTreeNodeSupplier.getNumberOfTreeNodes(
                DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ) > aTarget.Paragraph,
            "implCreateIteratedNodes(): paragraph index out of range" );
        
        pTargetSubset.reset( 
            new ShapeSubset( 
                pTargetShape,
                // retrieve index aTarget.Paragraph of
                // type PARAGRAPH from this shape
                rTreeNodeSupplier.getTreeNode(
                    aTarget.Paragraph,
                    DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ),
                rContext.maContext.mpSubsettableShapeManager ) );
        
        // iterate target is not the whole shape, but only
        // the selected paragraph - subset _must_ be
        // independent, to be able to affect visibility
        // independent of master shape
        aContext.mbIsIndependentSubset = true;
        
        // already enable parent subset right here, to
        // make potentially generated subsets subtract
        // their content from the parent subset (and not
        // the original shape). Otherwise, already
        // subsetted parents (e.g. paragraphs) would not
        // have their characters removed, when the child
        // iterations start.
        // Furthermore, the setup of initial shape
        // attributes of course needs the subset shape
        // generated, to apply e.g. visibility changes.
        pTargetSubset->enableSubsetShape();
    }
    else
    {
        pTargetSubset.reset( 
            new ShapeSubset( pTargetShape,
                             rContext.maContext.mpSubsettableShapeManager ));
    }
    
    aContext.mpMasterShapeSubset = pTargetSubset;
    uno::Reference< animations::XAnimationNode > xNode( xIterNode,
                                                        uno::UNO_QUERY_THROW );
    
    // Generate subsets
    // ================
    
    if( bParagraphTarget ||
        nSubItem != presentation::ShapeAnimationSubType::ONLY_TEXT )
    {
        // prepend with animations for
        // full Shape (will be subtracted
        // from the subset parts within
        // the Shape::createSubset()
        // method). For ONLY_TEXT effects,
        // we skip this part, to animate
        // only the text.
        // 
        // OR
        //
        // prepend with subset animation for full
        // _paragraph_, from which the individual
        // paragraph subsets are subtracted. Note that the
        // subitem is superfluous here, we always assume
        // ONLY_TEXT, if a paragraph is referenced as the
        // master of an iteration effect.
        NodeCreator aCreator( rParent, aContext );
        if( !::anim::for_each_childNode( xNode, 
                                         aCreator ) )
        {
            ENSURE_OR_RETURN_FALSE(
                false, 
                "implCreateIteratedNodes(): iterated child node creation failed" );
        }                        
    }
    
    // TODO(F2): This does not do the correct
    // thing. Having nSubItem be set to ONLY_BACKGROUND
    // should result in the text staying unanimated in the
    // foreground, while the shape moves in the background
    // (this behaviour is perfectly possible with the
    // slideshow engine, only that the text won't be
    // currently visible, because animations are always in
    // the foreground)
    if( nSubItem != presentation::ShapeAnimationSubType::ONLY_BACKGROUND )
    {
        // determine type of subitem iteration (logical
        // text unit to animate)
        DocTreeNode::NodeType eIterateNodeType( 
            DocTreeNode::NODETYPE_LOGICAL_CHARACTER_CELL );
        
        switch( xIterNode->getIterateType() )
        {
        case presentation::TextAnimationType::BY_PARAGRAPH:
            eIterateNodeType = DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH;
            break;
            
        case presentation::TextAnimationType::BY_WORD:
            eIterateNodeType = DocTreeNode::NODETYPE_LOGICAL_WORD;
            break;
            
        case presentation::TextAnimationType::BY_LETTER:
            eIterateNodeType = DocTreeNode::NODETYPE_LOGICAL_CHARACTER_CELL;
            break;
            
        default:
            ENSURE_OR_THROW(
                false, "implCreateIteratedNodes(): "
                "Unexpected IterateType on XIterateContainer");
            break;
        }
        
        if( bParagraphTarget && 
            eIterateNodeType != DocTreeNode::NODETYPE_LOGICAL_WORD &&
            eIterateNodeType != DocTreeNode::NODETYPE_LOGICAL_CHARACTER_CELL )
        {
            // will not animate the whole paragraph, when
            // only the paragraph is animated at all.
            OSL_ENSURE( false,
                        "implCreateIteratedNodes(): Ignoring paragraph iteration for paragraph master" );
        }
        else
        {
            // setup iteration parameters
            // --------------------------
            
            // iterate target is the whole shape (or the
            // whole parent subshape), thus, can save
            // loads of subset shapes by generating them
            // only when the effects become active -
            // before and after the effect active
            // duration, all attributes are shared by
            // master shape and subset (since the iterated
            // effects are all the same).
            aContext.mbIsIndependentSubset = false;
            
            // determine number of nodes for given subitem
            // type
            sal_Int32 nTreeNodes( 0 );
            if( bParagraphTarget )
            {
                // create the iterated subset _relative_ to
                // the given paragraph index (i.e. animate the
                // given subset type, but only when it's part
                // of the given paragraph)
                nTreeNodes = rTreeNodeSupplier.getNumberOfSubsetTreeNodes(
                    pTargetSubset->getSubset(),
                    eIterateNodeType );
            }
            else
            {
                // generate normal subset
                nTreeNodes = rTreeNodeSupplier.getNumberOfTreeNodes( 
                    eIterateNodeType );
            }
            
            
            // iterate node, generate copies of the children for each subset
            // -------------------------------------------------------------
            
            // NodeContext::mnStartDelay contains additional node delay.
            // This will make the duplicated nodes for each iteration start
            // increasingly later.
            aContext.mnStartDelay = nIntervalTimeout; 
            
            for( sal_Int32 i=0; i<nTreeNodes; ++i )
            {
                // create subset with the corresponding tree nodes
                if( bParagraphTarget )
                {
                    // create subsets relative to paragraph subset
                    aContext.mpMasterShapeSubset.reset( 
                        new ShapeSubset(
                            pTargetSubset,
                            rTreeNodeSupplier.getSubsetTreeNode(
                                pTargetSubset->getSubset(),
                                i,
                                eIterateNodeType ) ) );
                }
                else
                {
                    // create subsets from main shape
                    aContext.mpMasterShapeSubset.reset( 
                        new ShapeSubset( pTargetSubset,
                                         rTreeNodeSupplier.getTreeNode(
                                             i,
                                             eIterateNodeType ) ) );
                }
                
                CloningNodeCreator aCreator( rParent, aContext );
                if( !::anim::for_each_childNode( xNode, 
                                                 aCreator ) )
                {
                    ENSURE_OR_RETURN_FALSE(
                        false, "implCreateIteratedNodes(): "
                        "iterated child node creation failed" );
                }
                
                aContext.mnStartDelay += nIntervalTimeout;
            }
        }
    }
    
    // done with iterate child generation
    return true;
}

BaseNodeSharedPtr implCreateAnimationNode(
    const uno::Reference< animations::XAnimationNode >&  xNode,
    const BaseContainerNodeSharedPtr&                    rParent,
    const NodeContext&                                   rContext )
{
    ENSURE_OR_THROW( xNode.is(),
                      "implCreateAnimationNode(): invalid XAnimationNode" );
    
    BaseNodeSharedPtr           pCreatedNode;
    BaseContainerNodeSharedPtr  pCreatedContainer;
    
    // create the internal node, corresponding to xNode
    switch( xNode->getType() )
    {
    case animations::AnimationNodeType::CUSTOM:
        OSL_ENSURE( false, "implCreateAnimationNode(): "
                    "CUSTOM not yet implemented" );
        return pCreatedNode;
        
    case animations::AnimationNodeType::PAR:
        pCreatedNode = pCreatedContainer = BaseContainerNodeSharedPtr(
            new ParallelTimeContainer( xNode, rParent, rContext ) );
        break;
        
    case animations::AnimationNodeType::ITERATE:
        // map iterate container to ParallelTimeContainer.
        // the iterating functionality is to be found
        // below, (see method implCreateIteratedNodes)
        pCreatedNode = pCreatedContainer = BaseContainerNodeSharedPtr(
            new ParallelTimeContainer( xNode, rParent, rContext ) );
        break;
        
    case animations::AnimationNodeType::SEQ:
        pCreatedNode = pCreatedContainer = BaseContainerNodeSharedPtr(
            new SequentialTimeContainer( xNode, rParent, rContext ) );
        break;
        
    case animations::AnimationNodeType::ANIMATE:
        pCreatedNode.reset( new PropertyAnimationNode(
                                xNode, rParent, rContext ) );
        break;
        
    case animations::AnimationNodeType::SET:
        pCreatedNode.reset( new AnimationSetNode(
                                xNode, rParent, rContext ) );
        break;
        
    case animations::AnimationNodeType::ANIMATEMOTION:
        pCreatedNode.reset( new AnimationPathMotionNode(
                                xNode, rParent, rContext ) );
        break;
        
    case animations::AnimationNodeType::ANIMATECOLOR:
        pCreatedNode.reset( new AnimationColorNode(
                                xNode, rParent, rContext ) );
        break;
        
    case animations::AnimationNodeType::ANIMATETRANSFORM:
        pCreatedNode.reset( new AnimationTransformNode(
                                xNode, rParent, rContext ) );
        break;
        
    case animations::AnimationNodeType::TRANSITIONFILTER:
        pCreatedNode.reset( new AnimationTransitionFilterNode(
                                xNode, rParent, rContext ) );
        break;
        
    case animations::AnimationNodeType::AUDIO:
        pCreatedNode.reset( new AnimationAudioNode(
                                xNode, rParent, rContext ) );
        break;
        
    case animations::AnimationNodeType::COMMAND:
        pCreatedNode.reset( new AnimationCommandNode(
                                xNode, rParent, rContext ) );
        break;
        
    default:
        OSL_ENSURE( false, "implCreateAnimationNode(): "
                    "invalid AnimationNodeType" );
        return pCreatedNode;
    }
    
    // TODO(Q1): This yields circular references, which, it seems, is 
    // unavoidable here
    
    // HACK: node objects need shared_ptr to themselves, 
    // which we pass them here.
    pCreatedNode->setSelf( pCreatedNode );
    
    // if we've got a container node object, recursively add 
    // its children
    if( pCreatedContainer )
    {
        uno::Reference< animations::XIterateContainer > xIterNode(
            xNode, uno::UNO_QUERY );
        
        // when this node is an XIterateContainer with
        // active iterations, this method will generate
        // the appropriate children
        if( xIterNode.is() )
        {
            // note that implCreateIteratedNodes() might
            // choose not to generate any child nodes
            // (e.g. when the iterate timeout is outside
            // sensible limits). Then, no child nodes are
            // generated at all, since typically, child
            // node attribute are incomplete for iteration
            // children.
            implCreateIteratedNodes( xIterNode,
                                     pCreatedContainer, 
                                     rContext );
        }
        else
        {
            // no iterate subset node, just plain child generation now
            NodeCreator aCreator( pCreatedContainer, rContext );
            if( !::anim::for_each_childNode( xNode, aCreator ) )
            {
                OSL_ENSURE( false, "implCreateAnimationNode(): "
                            "child node creation failed" );
                return BaseNodeSharedPtr();
            }
        }
    }                    
    
    return pCreatedNode;
}

} // anon namespace

AnimationNodeSharedPtr AnimationNodeFactory::createAnimationNode(
    const uno::Reference< animations::XAnimationNode >&   xNode,
    const ::basegfx::B2DVector&                           rSlideSize,
    const SlideShowContext&                               rContext )
{
    ENSURE_OR_THROW(
        xNode.is(),
        "AnimationNodeFactory::createAnimationNode(): invalid XAnimationNode" );
    
    return BaseNodeSharedPtr( implCreateAnimationNode(
                                  xNode, 
                                  BaseContainerNodeSharedPtr(), // no parent
                                  NodeContext( rContext,
                                               rSlideSize )));
}

#if defined(VERBOSE) && defined(DBG_UTIL)
void AnimationNodeFactory::showTree( AnimationNodeSharedPtr& pRootNode )
{
    if( pRootNode )
        DEBUG_NODES_SHOWTREE( boost::dynamic_pointer_cast<BaseContainerNode>(
                                  pRootNode).get() );
}
#endif

} // namespace internal
} // namespace slideshow

