/*
 * 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;
            mPendingActionUponFinish = Action::None;
            break;
        case Request::Reverse:
            mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing)
                                ? mPlayTime
                                : mDuration;
            mPlayState = PlayState::Reversing;
            mPendingActionUponFinish = Action::None;
            break;
        case Request::Reset:
            mPlayTime = 0;
            mPlayState = PlayState::Finished;
            mPendingActionUponFinish = Action::Reset;
            break;
        case Request::Cancel:
            mPlayState = PlayState::Finished;
            mPendingActionUponFinish = Action::None;
            break;
        case Request::End:
            mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration;
            mPlayState = PlayState::Finished;
            mPendingActionUponFinish = Action::End;
            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 (!mStagingRequests.empty()) {
        // No interpolator was set, use the default
        if (mPlayState == PlayState::NotStarted && !mInterpolator) {
            mInterpolator.reset(Interpolator::createDefaultInterpolator());
        }
        // 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) {
            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;
    }
    if (mDuration < 0) {
        ALOGW("Your duration is strange and confusing: %" PRId64, mDuration);
    }
}

bool BaseRenderNodeAnimator::animate(AnimationContext& context) {
    if (mPlayState < PlayState::Running) {
        return false;
    }
    if (mPlayState == PlayState::Finished) {
        if (mPendingActionUponFinish == Action::Reset) {
            // Skip to start.
            updatePlayTime(0);
        } else if (mPendingActionUponFinish == Action::End) {
            // Skip to end.
            updatePlayTime(mDuration);
        }
        // Reset pending action.
        mPendingActionUponFinish = Action::None;
        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) {
        return false;
    }
    if (!this->mHasStartValue) {
        doSetStartValue(getValue(mTarget));
    }

    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;
}

nsecs_t BaseRenderNodeAnimator::getRemainingPlayTime() {
    return mPlayState == PlayState::Reversing ? mPlayTime : mDuration - mPlayTime;
}

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_Z, &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 */
