/*
 * 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/config.h"
#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
