/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed 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.
 */

#include "Animator.h"

#include <inttypes.h>
#include <set>

#include "AnimationContext.h"
#include "Interpolator.h"
#include "RenderNode.h"
#include "RenderProperties.h"

namespace android {
namespace uirenderer {

/************************************************************
 *  BaseRenderNodeAnimator
 ************************************************************/

BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue)
        : mTarget(nullptr)
        , mStagingTarget(nullptr)
        , mFinalValue(finalValue)
        , mDeltaValue(0)
        , mFromValue(0)
        , mStagingPlayState(PlayState::NotStarted)
        , mPlayState(PlayState::NotStarted)
        , mHasStartValue(false)
        , mStartTime(0)
        , mDuration(300)
        , mStartDelay(0)
        , mMayRunAsync(true)
        , mPlayTime(0) {
}

BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
}

void BaseRenderNodeAnimator::checkMutable() {
    // Should be impossible to hit as the Java-side also has guards for this
    LOG_ALWAYS_FATAL_IF(mStagingPlayState != PlayState::NotStarted,
            "Animator has already been started!");
}

void BaseRenderNodeAnimator::setInterpolator(Interpolator* interpolator) {
    checkMutable();
    mInterpolator.reset(interpolator);
}

void BaseRenderNodeAnimator::setStartValue(float value) {
    checkMutable();
    doSetStartValue(value);
}

void BaseRenderNodeAnimator::doSetStartValue(float value) {
    mFromValue = value;
    mDeltaValue = (mFinalValue - mFromValue);
    mHasStartValue = true;
}

void BaseRenderNodeAnimator::setDuration(nsecs_t duration) {
    checkMutable();
    mDuration = duration;
}

void BaseRenderNodeAnimator::setStartDelay(nsecs_t startDelay) {
    checkMutable();
    mStartDelay = startDelay;
}

void BaseRenderNodeAnimator::attach(RenderNode* target) {
    mStagingTarget = target;
    onAttached();
}

void BaseRenderNodeAnimator::start() {
    mStagingPlayState = PlayState::Running;
    mStagingRequests.push_back(Request::Start);
    onStagingPlayStateChanged();
}

void BaseRenderNodeAnimator::cancel() {
    mStagingPlayState = PlayState::Finished;
    mStagingRequests.push_back(Request::Cancel);
    onStagingPlayStateChanged();
}

void BaseRenderNodeAnimator::reset() {
    mStagingPlayState = PlayState::Finished;
    mStagingRequests.push_back(Request::Reset);
    onStagingPlayStateChanged();
}

void BaseRenderNodeAnimator::reverse() {
    mStagingPlayState = PlayState::Reversing;
    mStagingRequests.push_back(Request::Reverse);
    onStagingPlayStateChanged();
}

void BaseRenderNodeAnimator::end() {
    mStagingPlayState = PlayState::Finished;
    mStagingRequests.push_back(Request::End);
    onStagingPlayStateChanged();
}

void BaseRenderNodeAnimator::resolveStagingRequest(Request request) {
    switch (request) {
    case Request::Start:
        mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
                        mPlayTime : 0;
        mPlayState = PlayState::Running;
        break;
    case Request::Reverse:
        mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
                        mPlayTime : mDuration;
        mPlayState = PlayState::Reversing;
        break;
    case Request::Reset:
        mPlayTime = 0;
        mPlayState = PlayState::Finished;
        break;
    case Request::Cancel:
        mPlayState = PlayState::Finished;
        break;
    case Request::End:
        mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration;
        mPlayState = PlayState::Finished;
        break;
    default:
        LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request));
    };
}

void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
    if (mStagingTarget) {
        RenderNode* oldTarget = mTarget;
        mTarget = mStagingTarget;
        mStagingTarget = nullptr;
        if (oldTarget && oldTarget != mTarget) {
            oldTarget->onAnimatorTargetChanged(this);
        }
    }

    if (!mHasStartValue) {
        doSetStartValue(getValue(mTarget));
    }

    if (!mStagingRequests.empty()) {
        // Keep track of the play state and play time before they are changed when
        // staging requests are resolved.
        nsecs_t currentPlayTime = mPlayTime;
        PlayState prevFramePlayState = mPlayState;

        // Resolve staging requests one by one.
        for (Request request : mStagingRequests) {
            resolveStagingRequest(request);
        }
        mStagingRequests.clear();

        if (mStagingPlayState == PlayState::Finished) {
            // Set the staging play time and end the animation
            updatePlayTime(mPlayTime);
            callOnFinishedListener(context);
        } else if (mStagingPlayState == PlayState::Running
                || mStagingPlayState == PlayState::Reversing) {
            bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState;
            if (prevFramePlayState != mStagingPlayState) {
                transitionToRunning(context);
            }
            if (changed) {
                // Now we need to seek to the stagingPlayTime (i.e. the animation progress that was
                // requested from UI thread). It is achieved by modifying mStartTime, such that
                // current time - mStartTime = stagingPlayTime (or mDuration -stagingPlayTime in the
                // case of reversing)
                nsecs_t currentFrameTime = context.frameTimeMs();
                if (mPlayState == PlayState::Reversing) {
                    // Reverse is not supported for animations with a start delay, so here we
                    // assume no start delay.
                    mStartTime = currentFrameTime  - (mDuration - mPlayTime);
                } else {
                    // Animation should play forward
                    if (mPlayTime == 0) {
                        // If the request is to start from the beginning, include start delay.
                        mStartTime = currentFrameTime + mStartDelay;
                    } else {
                        // If the request is to seek to a non-zero play time, then we skip start
                        // delay.
                        mStartTime = currentFrameTime - mPlayTime;
                    }
                }
            }
        }
    }
    onPushStaging();
}

void BaseRenderNodeAnimator::transitionToRunning(AnimationContext& context) {
    nsecs_t frameTimeMs = context.frameTimeMs();
    LOG_ALWAYS_FATAL_IF(frameTimeMs <= 0, "%" PRId64 " isn't a real frame time!", frameTimeMs);
    if (mStartDelay < 0 || mStartDelay > 50000) {
        ALOGW("Your start delay is strange and confusing: %" PRId64, mStartDelay);
    }
    mStartTime = frameTimeMs + mStartDelay;
    if (mStartTime < 0) {
        ALOGW("Ended up with a really weird start time of %" PRId64
                " with frame time %" PRId64 " and start delay %" PRId64,
                mStartTime, frameTimeMs, mStartDelay);
        // Set to 0 so that the animate() basically instantly finishes
        mStartTime = 0;
    }
    // No interpolator was set, use the default
    if (!mInterpolator) {
        mInterpolator.reset(Interpolator::createDefaultInterpolator());
    }
    if (mDuration < 0 || mDuration > 50000) {
        ALOGW("Your duration is strange and confusing: %" PRId64, mDuration);
    }
}

bool BaseRenderNodeAnimator::animate(AnimationContext& context) {
    if (mPlayState < PlayState::Running) {
        return false;
    }
    if (mPlayState == PlayState::Finished) {
        return true;
    }

    // This should be set before setValue() so animators can query this time when setValue
    // is called.
    nsecs_t currentPlayTime = context.frameTimeMs() - mStartTime;
    bool finished = updatePlayTime(currentPlayTime);
    if (finished && mPlayState != PlayState::Finished) {
        mPlayState = PlayState::Finished;
        callOnFinishedListener(context);
    }
    return finished;
}

bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) {
    mPlayTime = mPlayState == PlayState::Reversing ? mDuration - playTime : playTime;
    onPlayTimeChanged(mPlayTime);
    // If BaseRenderNodeAnimator is handling the delay (not typical), then
    // because the staging properties reflect the final value, we always need
    // to call setValue even if the animation isn't yet running or is still
    // being delayed as we need to override the staging value
    if (playTime < 0) {
        setValue(mTarget, mFromValue);
        return false;
    }

    float fraction = 1.0f;
    if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) {
        fraction = mPlayTime / (float) mDuration;
    }
    fraction = MathUtils::clamp(fraction, 0.0f, 1.0f);

    fraction = mInterpolator->interpolate(fraction);
    setValue(mTarget, mFromValue + (mDeltaValue * fraction));

    return playTime >= mDuration;
}

void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
    if (mPlayState < PlayState::Finished) {
        mPlayState = PlayState::Finished;
        callOnFinishedListener(context);
    }
}

void BaseRenderNodeAnimator::callOnFinishedListener(AnimationContext& context) {
    if (mListener.get()) {
        context.callOnFinished(this, mListener.get());
    }
}

/************************************************************
 *  RenderPropertyAnimator
 ************************************************************/

struct RenderPropertyAnimator::PropertyAccessors {
   RenderNode::DirtyPropertyMask dirtyMask;
   GetFloatProperty getter;
   SetFloatProperty setter;
};

// Maps RenderProperty enum to accessors
const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
    {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
    {RenderNode::TRANSLATION_Y, &RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
    {RenderNode::TRANSLATION_X, &RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
    {RenderNode::SCALE_X, &RenderProperties::getScaleX, &RenderProperties::setScaleX },
    {RenderNode::SCALE_Y, &RenderProperties::getScaleY, &RenderProperties::setScaleY },
    {RenderNode::ROTATION, &RenderProperties::getRotation, &RenderProperties::setRotation },
    {RenderNode::ROTATION_X, &RenderProperties::getRotationX, &RenderProperties::setRotationX },
    {RenderNode::ROTATION_Y, &RenderProperties::getRotationY, &RenderProperties::setRotationY },
    {RenderNode::X, &RenderProperties::getX, &RenderProperties::setX },
    {RenderNode::Y, &RenderProperties::getY, &RenderProperties::setY },
    {RenderNode::Z, &RenderProperties::getZ, &RenderProperties::setZ },
    {RenderNode::ALPHA, &RenderProperties::getAlpha, &RenderProperties::setAlpha },
};

RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property, float finalValue)
        : BaseRenderNodeAnimator(finalValue)
        , mPropertyAccess(&(PROPERTY_ACCESSOR_LUT[property])) {
}

void RenderPropertyAnimator::onAttached() {
    if (!mHasStartValue
            && mStagingTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
        setStartValue((mStagingTarget->stagingProperties().*mPropertyAccess->getter)());
    }
}

void RenderPropertyAnimator::onStagingPlayStateChanged() {
    if (mStagingPlayState == PlayState::Running) {
        if (mStagingTarget) {
            (mStagingTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
        } else {
            // In the case of start delay where stagingTarget has been sync'ed over and null'ed
            // we delay the properties update to push staging.
            mShouldUpdateStagingProperties = true;
        }
    } else if (mStagingPlayState == PlayState::Finished) {
        // We're being canceled, so make sure that whatever values the UI thread
        // is observing for us is pushed over
        mShouldSyncPropertyFields = true;
    }
}

void RenderPropertyAnimator::onPushStaging() {
    if (mShouldUpdateStagingProperties) {
        (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
        mShouldUpdateStagingProperties = false;
    }

    if (mShouldSyncPropertyFields) {
        mTarget->setPropertyFieldsDirty(dirtyMask());
        mShouldSyncPropertyFields = false;
    }
}

uint32_t RenderPropertyAnimator::dirtyMask() {
    return mPropertyAccess->dirtyMask;
}

float RenderPropertyAnimator::getValue(RenderNode* target) const {
    return (target->properties().*mPropertyAccess->getter)();
}

void RenderPropertyAnimator::setValue(RenderNode* target, float value) {
    (target->animatorProperties().*mPropertyAccess->setter)(value);
}

/************************************************************
 *  CanvasPropertyPrimitiveAnimator
 ************************************************************/

CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
                CanvasPropertyPrimitive* property, float finalValue)
        : BaseRenderNodeAnimator(finalValue)
        , mProperty(property) {
}

float CanvasPropertyPrimitiveAnimator::getValue(RenderNode* target) const {
    return mProperty->value;
}

void CanvasPropertyPrimitiveAnimator::setValue(RenderNode* target, float value) {
    mProperty->value = value;
}

uint32_t CanvasPropertyPrimitiveAnimator::dirtyMask() {
    return RenderNode::DISPLAY_LIST;
}

/************************************************************
 *  CanvasPropertySkPaintAnimator
 ************************************************************/

CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
                CanvasPropertyPaint* property, PaintField field, float finalValue)
        : BaseRenderNodeAnimator(finalValue)
        , mProperty(property)
        , mField(field) {
}

float CanvasPropertyPaintAnimator::getValue(RenderNode* target) const {
    switch (mField) {
    case STROKE_WIDTH:
        return mProperty->value.getStrokeWidth();
    case ALPHA:
        return mProperty->value.getAlpha();
    }
    LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
    return -1;
}

static uint8_t to_uint8(float value) {
    int c = (int) (value + .5f);
    return static_cast<uint8_t>( c < 0 ? 0 : c > 255 ? 255 : c );
}

void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) {
    switch (mField) {
    case STROKE_WIDTH:
        mProperty->value.setStrokeWidth(value);
        return;
    case ALPHA:
        mProperty->value.setAlpha(to_uint8(value));
        return;
    }
    LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
}

uint32_t CanvasPropertyPaintAnimator::dirtyMask() {
    return RenderNode::DISPLAY_LIST;
}

RevealAnimator::RevealAnimator(int centerX, int centerY,
        float startValue, float finalValue)
        : BaseRenderNodeAnimator(finalValue)
        , mCenterX(centerX)
        , mCenterY(centerY) {
    setStartValue(startValue);
}

float RevealAnimator::getValue(RenderNode* target) const {
    return target->properties().getRevealClip().getRadius();
}

void RevealAnimator::setValue(RenderNode* target, float value) {
    target->animatorProperties().mutableRevealClip().set(true,
            mCenterX, mCenterY, value);
}

uint32_t RevealAnimator::dirtyMask() {
    return RenderNode::GENERIC;
}

} /* namespace uirenderer */
} /* namespace android */
