/*
 * Copyright (C) 2019 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "config.h"
#include "WebAnimationUtilities.h"

#include "Animation.h"
#include "AnimationList.h"
#include "CSSAnimation.h"
#include "CSSTransition.h"
#include "DeclarativeAnimation.h"
#include "Element.h"
#include "KeyframeEffectStack.h"
#include "PseudoElement.h"
#include "WebAnimation.h"

namespace WebCore {

static bool compareDeclarativeAnimationOwningElementPositionsInDocumentTreeOrder(Element& a, Element& b)
{
    // We should not ever be calling this function with two Elements that are the same. If that were the case,
    // then comparing objects of this kind would yield inconsistent results when comparing A == B and B == A.
    // As such, this function should be called with std::stable_sort().
    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(&a != &b);

    // With regard to pseudo-elements, the sort order is as follows:
    //     - element
    //     - ::before
    //     - ::after
    //     - element children

    enum SortingIndex : uint8_t { NotPseudo, Before, After };

    int aSortingIndex = NotPseudo;
    Element* aReferenceElement = &a;
    if (is<PseudoElement>(a)) {
        auto& aPseudo = downcast<PseudoElement>(a);
        aSortingIndex = aPseudo.isBeforePseudoElement() ? Before : After;
        aReferenceElement = aPseudo.hostElement();
        ASSERT(aReferenceElement);
    }

    int bSortingIndex = NotPseudo;
    Element* bReferenceElement = &b;
    if (is<PseudoElement>(b)) {
        auto& bPseudo = downcast<PseudoElement>(b);
        bSortingIndex = bPseudo.isBeforePseudoElement() ? Before : After;
        bReferenceElement = bPseudo.hostElement();
        ASSERT(bReferenceElement);
    }

    if (aReferenceElement == bReferenceElement)
        return aSortingIndex < bSortingIndex;
    return aReferenceElement->compareDocumentPosition(*bReferenceElement) & Node::DOCUMENT_POSITION_FOLLOWING;
}

static bool compareCSSTransitions(const CSSTransition& a, const CSSTransition& b)
{
    ASSERT(a.owningElement());
    ASSERT(b.owningElement());
    auto& aOwningElement = *a.owningElement();
    auto& bOwningElement = *b.owningElement();

    // If the owning element of A and B differs, sort A and B by tree order of their corresponding owning elements.
    if (&aOwningElement != &bOwningElement)
        return compareDeclarativeAnimationOwningElementPositionsInDocumentTreeOrder(aOwningElement, bOwningElement);

    // Otherwise, if A and B have different transition generation values, sort by their corresponding transition generation in ascending order.
    if (a.generationTime() != b.generationTime())
        return a.generationTime() < b.generationTime();

    // Otherwise, sort A and B in ascending order by the Unicode codepoints that make up the expanded transition property name of each transition
    // (i.e. without attempting case conversion and such that ‘-moz-column-width’ sorts before ‘column-width’).
    return a.transitionProperty().utf8() < b.transitionProperty().utf8();
}

static bool compareCSSAnimations(const CSSAnimation& a, const CSSAnimation& b)
{
    // https://drafts.csswg.org/css-animations-2/#animation-composite-order
    ASSERT(a.owningElement());
    ASSERT(b.owningElement());
    auto& aOwningElement = *a.owningElement();
    auto& bOwningElement = *b.owningElement();

    // If the owning element of A and B differs, sort A and B by tree order of their corresponding owning elements.
    if (&aOwningElement != &bOwningElement)
        return compareDeclarativeAnimationOwningElementPositionsInDocumentTreeOrder(aOwningElement, bOwningElement);

    // Sort A and B based on their position in the computed value of the animation-name property of the (common) owning element.
    auto* cssAnimationList = aOwningElement.ensureKeyframeEffectStack().cssAnimationList();
    ASSERT(cssAnimationList);
    ASSERT(!cssAnimationList->isEmpty());

    auto& aBackingAnimation = a.backingAnimation();
    auto& bBackingAnimation = b.backingAnimation();
    for (size_t i = 0; i < cssAnimationList->size(); ++i) {
        auto& animation = cssAnimationList->animation(i);
        if (animation == aBackingAnimation)
            return true;
        if (animation == bBackingAnimation)
            return false;
    }

    // We should have found either of those CSS animations in the CSS animations list.
    RELEASE_ASSERT_NOT_REACHED();
}

bool compareAnimationsByCompositeOrder(const WebAnimation& a, const WebAnimation& b)
{
    // We should not ever be calling this function with two WebAnimation objects that are the same. If that were the case,
    // then comparing objects of this kind would yield inconsistent results when comparing A == B and B == A. As such,
    // this function should be called with std::stable_sort().
    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(&a != &b);

    bool aHasOwningElement = is<DeclarativeAnimation>(a) && downcast<DeclarativeAnimation>(a).owningElement();
    bool bHasOwningElement = is<DeclarativeAnimation>(b) && downcast<DeclarativeAnimation>(b).owningElement();

    // CSS Transitions sort first.
    bool aIsCSSTransition = aHasOwningElement && is<CSSTransition>(a);
    bool bIsCSSTransition = bHasOwningElement && is<CSSTransition>(b);
    if (aIsCSSTransition || bIsCSSTransition) {
        if (aIsCSSTransition == bIsCSSTransition)
            return compareCSSTransitions(downcast<CSSTransition>(a), downcast<CSSTransition>(b));
        return !bIsCSSTransition;
    }

    // CSS Animations sort next.
    bool aIsCSSAnimation = aHasOwningElement && is<CSSAnimation>(a);
    bool bIsCSSAnimation = bHasOwningElement && is<CSSAnimation>(b);
    if (aIsCSSAnimation || bIsCSSAnimation) {
        if (aIsCSSAnimation == bIsCSSAnimation)
            return compareCSSAnimations(downcast<CSSAnimation>(a), downcast<CSSAnimation>(b));
        return !bIsCSSAnimation;
    }

    // JS-originated animations sort last based on their position in the global animation list.
    // https://drafts.csswg.org/web-animations-1/#animation-composite-order
    RELEASE_ASSERT(a.globalPosition() != b.globalPosition());
    return a.globalPosition() < b.globalPosition();
}

} // namespace WebCore
