/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "sky/engine/core/animation/AnimationStack.h"

#include <algorithm>
#include "sky/engine/core/animation/StyleInterpolation.h"
#include "sky/engine/core/animation/css/CSSAnimations.h"
#include "sky/engine/wtf/BitArray.h"
#include "sky/engine/wtf/NonCopyingSort.h"

namespace blink {

namespace {

void copyToActiveInterpolationMap(const Vector<RefPtr<blink::Interpolation> >& source, HashMap<CSSPropertyID, RefPtr<blink::Interpolation> >& target)
{
    for (size_t i = 0; i < source.size(); ++i) {
        Interpolation* interpolation = source[i].get();
        target.set(toStyleInterpolation(interpolation)->id(), interpolation);
    }
}

bool compareEffects(const OwnPtr<SampledEffect>& effect1, const OwnPtr<SampledEffect>& effect2)
{
    ASSERT(effect1 && effect2);
    return effect1->sequenceNumber() < effect2->sequenceNumber();
}

void copyNewAnimationsToActiveInterpolationMap(const Vector<RawPtr<InertAnimation> >& newAnimations, HashMap<CSSPropertyID, RefPtr<Interpolation> >& result)
{
    for (size_t i = 0; i < newAnimations.size(); ++i) {
        OwnPtr<Vector<RefPtr<Interpolation> > > sample = newAnimations[i]->sample(0);
        if (sample) {
            copyToActiveInterpolationMap(*sample, result);
        }
    }
}

} // namespace

AnimationStack::AnimationStack()
{
}

HashMap<CSSPropertyID, RefPtr<Interpolation> > AnimationStack::activeInterpolations(AnimationStack* animationStack, const Vector<RawPtr<InertAnimation> >* newAnimations, const HashSet<RawPtr<const AnimationPlayer> >* cancelledAnimationPlayers, Animation::Priority priority, double timelineCurrentTime)
{
    // We don't exactly know when new animations will start, but timelineCurrentTime is a good estimate.

    HashMap<CSSPropertyID, RefPtr<Interpolation> > result;

    if (animationStack) {
        Vector<OwnPtr<SampledEffect> >& effects = animationStack->m_effects;
        // std::sort doesn't work with OwnPtrs
        nonCopyingSort(effects.begin(), effects.end(), compareEffects);
        animationStack->simplifyEffects();
        for (size_t i = 0; i < effects.size(); ++i) {
            const SampledEffect& effect = *effects[i];
            if (effect.priority() != priority || (cancelledAnimationPlayers && effect.animation() && cancelledAnimationPlayers->contains(effect.animation()->player())))
                continue;
            copyToActiveInterpolationMap(effect.interpolations(), result);
        }
    }

    if (newAnimations)
        copyNewAnimationsToActiveInterpolationMap(*newAnimations, result);

    return result;
}

void AnimationStack::simplifyEffects()
{
    // FIXME: This will need to be updated when we have 'add' keyframes.

    BitArray<numCSSProperties> replacedProperties;
    for (size_t i = m_effects.size(); i--; ) {
        SampledEffect& effect = *m_effects[i];
        effect.removeReplacedInterpolationsIfNeeded(replacedProperties);
        if (!effect.canChange()) {
            for (size_t i = 0; i < effect.interpolations().size(); ++i)
                replacedProperties.set(toStyleInterpolation(effect.interpolations()[i].get())->id());
        }
    }

    size_t dest = 0;
    for (size_t i = 0; i < m_effects.size(); ++i) {
        if (!m_effects[i]->interpolations().isEmpty()) {
            m_effects[dest++].swap(m_effects[i]);
            continue;
        }
        if (m_effects[i]->animation())
            m_effects[i]->animation()->notifySampledEffectRemovedFromAnimationStack();
    }
    m_effects.shrink(dest);
}

} // namespace blink
