/*
 * Copyright (C) 2017-2018 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 "AnimationEffect.h"

#include "FillMode.h"
#include "JSComputedEffectTiming.h"
#include "WebAnimationUtilities.h"

namespace WebCore {

AnimationEffect::AnimationEffect()
    : m_timingFunction(LinearTimingFunction::create())
{
}

AnimationEffect::~AnimationEffect()
{
}

EffectTiming AnimationEffect::getTiming() const
{
    EffectTiming timing;
    timing.delay = secondsToWebAnimationsAPITime(m_delay);
    timing.endDelay = secondsToWebAnimationsAPITime(m_endDelay);
    timing.fill = m_fill;
    timing.iterationStart = m_iterationStart;
    timing.iterations = m_iterations;
    if (m_iterationDuration == 0_s)
        timing.duration = "auto";
    else
        timing.duration = secondsToWebAnimationsAPITime(m_iterationDuration);
    timing.direction = m_direction;
    timing.easing = m_timingFunction->cssText();
    return timing;
}

BasicEffectTiming AnimationEffect::getBasicTiming() const
{
    // The Web Animations spec introduces a number of animation effect time-related definitions that refer
    // to each other a fair bit, so rather than implementing them as individual methods, it's more efficient
    // to return them all as a single BasicEffectTiming.

    auto localTime = [this]() -> Optional<Seconds> {
        // 4.5.4. Local time
        // https://drafts.csswg.org/web-animations-1/#local-time-section

        // The local time of an animation effect at a given moment is based on the first matching condition from the following:
        // If the animation effect is associated with an animation, the local time is the current time of the animation.
        // Otherwise, the local time is unresolved.
        if (m_animation)
            return m_animation->currentTime();
        return WTF::nullopt;
    }();

    auto phase = [this, localTime]() -> AnimationEffectPhase {
        // 3.5.5. Animation effect phases and states
        // https://drafts.csswg.org/web-animations-1/#animation-effect-phases-and-states

        bool animationIsBackwards = m_animation && m_animation->playbackRate() < 0;
        auto beforeActiveBoundaryTime = std::max(std::min(m_delay, m_endTime), 0_s);
        auto activeAfterBoundaryTime = std::max(std::min(m_delay + m_activeDuration, m_endTime), 0_s);

        // (This should be the last statement, but it's more efficient to cache the local time and return right away if it's not resolved.)
        // Furthermore, it is often convenient to refer to the case when an animation effect is in none of the above phases
        // as being in the idle phase.
        if (!localTime)
            return AnimationEffectPhase::Idle;

        // An animation effect is in the before phase if the animation effect’s local time is not unresolved and
        // either of the following conditions are met:
        //     1. the local time is less than the before-active boundary time, or
        //     2. the animation direction is ‘backwards’ and the local time is equal to the before-active boundary time.
        if ((*localTime + timeEpsilon) < beforeActiveBoundaryTime || (animationIsBackwards && std::abs(localTime->microseconds() - beforeActiveBoundaryTime.microseconds()) < timeEpsilon.microseconds()))
            return AnimationEffectPhase::Before;

        // An animation effect is in the after phase if the animation effect’s local time is not unresolved and
        // either of the following conditions are met:
        //     1. the local time is greater than the active-after boundary time, or
        //     2. the animation direction is ‘forwards’ and the local time is equal to the active-after boundary time.
        if ((*localTime - timeEpsilon) > activeAfterBoundaryTime || (!animationIsBackwards && std::abs(localTime->microseconds() - activeAfterBoundaryTime.microseconds()) < timeEpsilon.microseconds()))
            return AnimationEffectPhase::After;

        // An animation effect is in the active phase if the animation effect’s local time is not unresolved and it is not
        // in either the before phase nor the after phase.
        // (No need to check, we've already established that local time was resolved).
        return AnimationEffectPhase::Active;
    }();

    auto activeTime = [this, localTime, phase]() -> Optional<Seconds> {
        // 3.8.3.1. Calculating the active time
        // https://drafts.csswg.org/web-animations-1/#calculating-the-active-time

        // The active time is based on the local time and start delay. However, it is only defined
        // when the animation effect should produce an output and hence depends on its fill mode
        // and phase as follows,

        // If the animation effect is in the before phase, the result depends on the first matching
        // condition from the following,
        if (phase == AnimationEffectPhase::Before) {
            // If the fill mode is backwards or both, return the result of evaluating
            // max(local time - start delay, 0).
            if (m_fill == FillMode::Backwards || m_fill == FillMode::Both)
                return std::max(*localTime - m_delay, 0_s);
            // Otherwise, return an unresolved time value.
            return WTF::nullopt;
        }

        // If the animation effect is in the active phase, return the result of evaluating local time - start delay.
        if (phase == AnimationEffectPhase::Active)
            return *localTime - m_delay;

        // If the animation effect is in the after phase, the result depends on the first matching
        // condition from the following,
        if (phase == AnimationEffectPhase::After) {
            // If the fill mode is forwards or both, return the result of evaluating
            // max(min(local time - start delay, active duration), 0).
            if (m_fill == FillMode::Forwards || m_fill == FillMode::Both)
                return std::max(std::min(*localTime - m_delay, m_activeDuration), 0_s);
            // Otherwise, return an unresolved time value.
            return WTF::nullopt;
        }

        // Otherwise (the local time is unresolved), return an unresolved time value.
        return WTF::nullopt;
    }();

    return { localTime, activeTime, m_endTime, m_activeDuration, phase };
}

ComputedEffectTiming AnimationEffect::getComputedTiming() const
{
    // The Web Animations spec introduces a number of animation effect time-related definitions that refer
    // to each other a fair bit, so rather than implementing them as individual methods, it's more efficient
    // to return them all as a single ComputedEffectTiming.

    auto basicEffectTiming = getBasicTiming();
    auto activeTime = basicEffectTiming.activeTime;
    auto phase = basicEffectTiming.phase;

    auto overallProgress = [this, phase, activeTime]() -> Optional<double> {
        // 3.8.3.2. Calculating the overall progress
        // https://drafts.csswg.org/web-animations-1/#calculating-the-overall-progress

        // The overall progress describes the number of iterations that have completed (including partial iterations) and is defined as follows:

        // 1. If the active time is unresolved, return unresolved.
        if (!activeTime)
            return WTF::nullopt;

        // 2. Calculate an initial value for overall progress based on the first matching condition from below,
        double overallProgress;

        if (!m_iterationDuration) {
            // If the iteration duration is zero, if the animation effect is in the before phase, let overall progress be zero,
            // otherwise, let it be equal to the iteration count.
            overallProgress = phase == AnimationEffectPhase::Before ? 0 : m_iterations;
        } else {
            // Otherwise, let overall progress be the result of calculating active time / iteration duration.
            overallProgress = secondsToWebAnimationsAPITime(*activeTime) / secondsToWebAnimationsAPITime(m_iterationDuration);
        }

        // 3. Return the result of calculating overall progress + iteration start.
        overallProgress += m_iterationStart;
        return std::abs(overallProgress);
    }();

    auto simpleIterationProgress = [this, overallProgress, phase, activeTime]() -> Optional<double> {
        // 3.8.3.3. Calculating the simple iteration progress
        // https://drafts.csswg.org/web-animations-1/#calculating-the-simple-iteration-progress

        // The simple iteration progress is a fraction of the progress through the current iteration that
        // ignores transformations to the time introduced by the playback direction or timing functions
        // applied to the effect, and is calculated as follows:

        // 1. If the overall progress is unresolved, return unresolved.
        if (!overallProgress)
            return WTF::nullopt;

        // 2. If overall progress is infinity, let the simple iteration progress be iteration start % 1.0,
        // otherwise, let the simple iteration progress be overall progress % 1.0.
        double simpleIterationProgress = std::isinf(*overallProgress) ? fmod(m_iterationStart, 1) : fmod(*overallProgress, 1);

        // 3. If all of the following conditions are true,
        //
        // the simple iteration progress calculated above is zero, and
        // the animation effect is in the active phase or the after phase, and
        // the active time is equal to the active duration, and
        // the iteration count is not equal to zero.
        // let the simple iteration progress be 1.0.
        if (!simpleIterationProgress && (phase == AnimationEffectPhase::Active || phase == AnimationEffectPhase::After) && std::abs(activeTime->microseconds() - m_activeDuration.microseconds()) < timeEpsilon.microseconds() && m_iterations)
            return 1;

        return simpleIterationProgress;
    }();

    auto currentIteration = [this, activeTime, phase, simpleIterationProgress, overallProgress]() -> Optional<double> {
        // 3.8.4. Calculating the current iteration
        // https://drafts.csswg.org/web-animations-1/#calculating-the-current-iteration

        // The current iteration can be calculated using the following steps:

        // 1. If the active time is unresolved, return unresolved.
        if (!activeTime)
            return WTF::nullopt;

        // 2. If the animation effect is in the after phase and the iteration count is infinity, return infinity.
        if (phase == AnimationEffectPhase::After && std::isinf(m_iterations))
            return std::numeric_limits<double>::infinity();

        // 3. If the simple iteration progress is 1.0, return floor(overall progress) - 1.
        if (*simpleIterationProgress == 1)
            return floor(*overallProgress) - 1;

        // 4. Otherwise, return floor(overall progress).
        return floor(*overallProgress);
    }();

    auto currentDirection = [this, currentIteration]() -> AnimationEffect::ComputedDirection {
        // 3.9.1. Calculating the directed progress
        // https://drafts.csswg.org/web-animations-1/#calculating-the-directed-progress

        // If playback direction is normal, let the current direction be forwards.
        if (m_direction == PlaybackDirection::Normal)
            return AnimationEffect::ComputedDirection::Forwards;
    
        // If playback direction is reverse, let the current direction be reverse.
        if (m_direction == PlaybackDirection::Reverse)
            return AnimationEffect::ComputedDirection::Reverse;

        if (!currentIteration)
            return AnimationEffect::ComputedDirection::Forwards;
    
        // Otherwise, let d be the current iteration.
        auto d = *currentIteration;
        // If playback direction is alternate-reverse increment d by 1.
        if (m_direction == PlaybackDirection::AlternateReverse)
            d++;
        // If d % 2 == 0, let the current direction be forwards, otherwise let the current direction be reverse.
        // If d is infinity, let the current direction be forwards.
        if (std::isinf(d) || !fmod(d, 2))
            return AnimationEffect::ComputedDirection::Forwards;
        return AnimationEffect::ComputedDirection::Reverse;
    }();

    auto directedProgress = [simpleIterationProgress, currentDirection]() -> Optional<double> {
        // 3.9.1. Calculating the directed progress
        // https://drafts.csswg.org/web-animations-1/#calculating-the-directed-progress

        // The directed progress is calculated from the simple iteration progress using the following steps:

        // 1. If the simple iteration progress is unresolved, return unresolved.
        if (!simpleIterationProgress)
            return WTF::nullopt;

        // 2. Calculate the current direction (we implement this as a separate method).

        // 3. If the current direction is forwards then return the simple iteration progress.
        if (currentDirection == AnimationEffect::ComputedDirection::Forwards)
            return *simpleIterationProgress;

        // Otherwise, return 1.0 - simple iteration progress.
        return 1 - *simpleIterationProgress;
    }();

    auto transformedProgress = [this, directedProgress, currentDirection, phase]() -> Optional<double> {
        // 3.10.1. Calculating the transformed progress
        // https://drafts.csswg.org/web-animations-1/#calculating-the-transformed-progress

        // The transformed progress is calculated from the directed progress using the following steps:
        //
        // 1. If the directed progress is unresolved, return unresolved.
        if (!directedProgress)
            return WTF::nullopt;

        if (auto iterationDuration = m_iterationDuration.seconds()) {
            bool before = false;
            // 2. Calculate the value of the before flag as follows:
            if (is<StepsTimingFunction>(m_timingFunction)) {
                // 1. Determine the current direction using the procedure defined in §3.9.1 Calculating the directed progress.
                // 2. If the current direction is forwards, let going forwards be true, otherwise it is false.
                bool goingForwards = currentDirection == AnimationEffect::ComputedDirection::Forwards;
                // 3. The before flag is set if the animation effect is in the before phase and going forwards is true;
                //    or if the animation effect is in the after phase and going forwards is false.
                before = (phase == AnimationEffectPhase::Before && goingForwards) || (phase == AnimationEffectPhase::After && !goingForwards);
            }

            // 3. Return the result of evaluating the animation effect’s timing function passing directed progress as the
            //    input progress value and before flag as the before flag.
            return m_timingFunction->transformTime(*directedProgress, iterationDuration, before);
        }

        return *directedProgress;
    }();

    ComputedEffectTiming computedTiming;
    computedTiming.delay = secondsToWebAnimationsAPITime(m_delay);
    computedTiming.endDelay = secondsToWebAnimationsAPITime(m_endDelay);
    computedTiming.fill = m_fill == FillMode::Auto ? FillMode::None : m_fill;
    computedTiming.iterationStart = m_iterationStart;
    computedTiming.iterations = m_iterations;
    computedTiming.duration = secondsToWebAnimationsAPITime(m_iterationDuration);
    computedTiming.direction = m_direction;
    computedTiming.easing = m_timingFunction->cssText();
    computedTiming.endTime = secondsToWebAnimationsAPITime(m_endTime);
    computedTiming.activeDuration = secondsToWebAnimationsAPITime(m_activeDuration);
    if (basicEffectTiming.localTime)
        computedTiming.localTime = secondsToWebAnimationsAPITime(*basicEffectTiming.localTime);
    computedTiming.simpleIterationProgress = simpleIterationProgress;
    computedTiming.progress = transformedProgress;
    computedTiming.currentIteration = currentIteration;
    computedTiming.phase = phase;
    return computedTiming;
}

ExceptionOr<void> AnimationEffect::updateTiming(Optional<OptionalEffectTiming> timing)
{
    // 6.5.4. Updating the timing of an AnimationEffect
    // https://drafts.csswg.org/web-animations/#updating-animationeffect-timing

    // To update the timing properties of an animation effect, effect, from an EffectTiming or OptionalEffectTiming object, input, perform the following steps:
    if (!timing)
        return { };

    Optional<ComputedEffectTiming> previousTiming;
    if (m_animation)
        previousTiming = getComputedTiming();

    // 1. If the iterationStart member of input is present and less than zero, throw a TypeError and abort this procedure.
    if (timing->iterationStart) {
        if (timing->iterationStart.value() < 0)
            return Exception { TypeError };
    }

    // 2. If the iterations member of input is present, and less than zero or is the value NaN, throw a TypeError and abort this procedure.
    if (timing->iterations) {
        if (timing->iterations.value() < 0 || std::isnan(timing->iterations.value()))
            return Exception { TypeError };
    }

    // 3. If the duration member of input is present, and less than zero or is the value NaN, throw a TypeError and abort this procedure.
    // FIXME: should it not throw an exception on a string other than "auto"?
    if (timing->duration) {
        if (WTF::holds_alternative<double>(timing->duration.value())) {
            auto durationAsDouble = WTF::get<double>(timing->duration.value());
            if (durationAsDouble < 0 || std::isnan(durationAsDouble))
                return Exception { TypeError };
        } else {
            if (WTF::get<String>(timing->duration.value()) != "auto")
                return Exception { TypeError };
        }
    }

    // 4. If the easing member of input is present but cannot be parsed using the <timing-function> production [CSS-EASING-1], throw a TypeError and abort this procedure.
    if (!timing->easing.isNull()) {
        auto timingFunctionResult = TimingFunction::createFromCSSText(timing->easing);
        if (timingFunctionResult.hasException())
            return timingFunctionResult.releaseException();
        m_timingFunction = timingFunctionResult.returnValue();
    }

    // 5. Assign each member present in input to the corresponding timing property of effect as follows:
    //
    //    delay → start delay
    //    endDelay → end delay
    //    fill → fill mode
    //    iterationStart → iteration start
    //    iterations → iteration count
    //    duration → iteration duration
    //    direction → playback direction
    //    easing → timing function

    if (timing->delay)
        m_delay = Seconds::fromMilliseconds(timing->delay.value());

    if (timing->endDelay)
        m_endDelay = Seconds::fromMilliseconds(timing->endDelay.value());

    if (timing->fill)
        m_fill = timing->fill.value();

    if (timing->iterationStart)
        m_iterationStart = timing->iterationStart.value();

    if (timing->iterations)
        m_iterations = timing->iterations.value();

    if (timing->duration)
        m_iterationDuration = WTF::holds_alternative<double>(timing->duration.value()) ? Seconds::fromMilliseconds(WTF::get<double>(timing->duration.value())) : 0_s;

    if (timing->direction)
        m_direction = timing->direction.value();

    updateStaticTimingProperties();

    if (m_animation)
        m_animation->effectTimingDidChange(previousTiming);

    return { };
}

void AnimationEffect::updateStaticTimingProperties()
{
    // 3.8.2. Calculating the active duration
    // https://drafts.csswg.org/web-animations-1/#calculating-the-active-duration

    // The active duration is calculated as follows:
    // active duration = iteration duration × iteration count
    // If either the iteration duration or iteration count are zero, the active duration is zero.
    if (!m_iterationDuration || !m_iterations)
        m_activeDuration = 0_s;
    else
        m_activeDuration = m_iterationDuration * m_iterations;

    // 3.5.3 The active interval
    // https://drafts.csswg.org/web-animations-1/#end-time

    // The end time of an animation effect is the result of evaluating max(start delay + active duration + end delay, 0).
    m_endTime = m_delay + m_activeDuration + m_endDelay;
    if (m_endTime < 0_s)
        m_endTime = 0_s;
}

ExceptionOr<void> AnimationEffect::setIterationStart(double iterationStart)
{
    // https://drafts.csswg.org/web-animations-1/#dom-animationeffecttiming-iterationstart
    // If an attempt is made to set this attribute to a value less than zero, a TypeError must
    // be thrown and the value of the iterationStart attribute left unchanged.
    if (iterationStart < 0)
        return Exception { TypeError };

    if (m_iterationStart == iterationStart)
        return { };

    m_iterationStart = iterationStart;

    return { };
}

ExceptionOr<void> AnimationEffect::setIterations(double iterations)
{
    // https://drafts.csswg.org/web-animations-1/#dom-animationeffecttiming-iterations
    // If an attempt is made to set this attribute to a value less than zero or a NaN value, a
    // TypeError must be thrown and the value of the iterations attribute left unchanged.
    if (iterations < 0 || std::isnan(iterations))
        return Exception { TypeError };

    if (m_iterations == iterations)
        return { };
        
    m_iterations = iterations;

    return { };
}

void AnimationEffect::setDelay(const Seconds& delay)
{
    if (m_delay == delay)
        return;

    m_delay = delay;
}

void AnimationEffect::setEndDelay(const Seconds& endDelay)
{
    if (m_endDelay == endDelay)
        return;

    m_endDelay = endDelay;
}

void AnimationEffect::setFill(FillMode fill)
{
    if (m_fill == fill)
        return;

    m_fill = fill;
}

void AnimationEffect::setIterationDuration(const Seconds& duration)
{
    if (m_iterationDuration == duration)
        return;

    m_iterationDuration = duration;
}

void AnimationEffect::setDirection(PlaybackDirection direction)
{
    if (m_direction == direction)
        return;

    m_direction = direction;
}

void AnimationEffect::setTimingFunction(const RefPtr<TimingFunction>& timingFunction)
{
    m_timingFunction = timingFunction;
}

} // namespace WebCore
