/*
 * Copyright (C) 2020 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 "PointerControllerContext.h"
#include "PointerController.h"

namespace {
// Time to wait before starting the fade when the pointer is inactive.
const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL;   // 3 seconds

// The number of events to be read at once for DisplayEventReceiver.
const int EVENT_BUFFER_SIZE = 100;
} // namespace

namespace android {

// --- PointerControllerContext ---

PointerControllerContext::PointerControllerContext(
        const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
        const sp<SpriteController>& spriteController, PointerController& controller)
      : mPolicy(policy),
        mLooper(looper),
        mSpriteController(spriteController),
        mHandler(new MessageHandler()),
        mCallback(new LooperCallback()),
        mController(controller),
        mAnimator(*this) {
    std::scoped_lock lock(mLock);
    mLocked.inactivityTimeout = InactivityTimeout::NORMAL;
}

PointerControllerContext::~PointerControllerContext() {
    mLooper->removeMessages(mHandler);
}

void PointerControllerContext::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
    std::scoped_lock lock(mLock);

    if (mLocked.inactivityTimeout != inactivityTimeout) {
        mLocked.inactivityTimeout = inactivityTimeout;
        resetInactivityTimeoutLocked();
    }
}

void PointerControllerContext::resetInactivityTimeout() {
    std::scoped_lock lock(mLock);
    resetInactivityTimeoutLocked();
}

void PointerControllerContext::resetInactivityTimeoutLocked() REQUIRES(mLock) {
    mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);

    nsecs_t timeout = mLocked.inactivityTimeout == InactivityTimeout::SHORT
            ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT
            : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
    mLooper->sendMessageDelayed(timeout, mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
}

void PointerControllerContext::removeInactivityTimeout() {
    std::scoped_lock lock(mLock);
    mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
}

nsecs_t PointerControllerContext::getAnimationTime() REQUIRES(mAnimator.mLock) {
    return mAnimator.getAnimationTimeLocked();
}

void PointerControllerContext::setHandlerController(std::shared_ptr<PointerController> controller) {
    mHandler->pointerController = controller;
}

void PointerControllerContext::setCallbackController(
        std::shared_ptr<PointerController> controller) {
    mCallback->pointerController = controller;
}

sp<PointerControllerPolicyInterface> PointerControllerContext::getPolicy() {
    return mPolicy;
}

sp<SpriteController> PointerControllerContext::getSpriteController() {
    return mSpriteController;
}

void PointerControllerContext::handleDisplayEvents() {
    mAnimator.handleVsyncEvents();
}

void PointerControllerContext::MessageHandler::handleMessage(const Message& message) {
    std::shared_ptr<PointerController> controller = pointerController.lock();

    if (controller == nullptr) {
        ALOGE("PointerController instance was released before processing message: what=%d",
              message.what);
        return;
    }
    switch (message.what) {
        case MSG_INACTIVITY_TIMEOUT:
            controller->doInactivityTimeout();
            break;
    }
}

int PointerControllerContext::LooperCallback::handleEvent(int /* fd */, int events,
                                                          void* /* data */) {
    std::shared_ptr<PointerController> controller = pointerController.lock();
    if (controller == nullptr) {
        ALOGW("PointerController instance was released with pending callbacks.  events=0x%x",
              events);
        return 0; // Remove the callback, the PointerController is gone anyways
    }
    if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
        ALOGE("Display event receiver pipe was closed or an error occurred.  events=0x%x", events);
        return 0; // remove the callback
    }

    if (!(events & Looper::EVENT_INPUT)) {
        ALOGW("Received spurious callback for unhandled poll event.  events=0x%x", events);
        return 1; // keep the callback
    }

    controller->mContext.handleDisplayEvents();
    return 1; // keep the callback
}

void PointerControllerContext::addAnimationCallback(int32_t displayId,
                                                    std::function<bool(nsecs_t)> callback) {
    mAnimator.addCallback(displayId, callback);
}

void PointerControllerContext::removeAnimationCallback(int32_t displayId) {
    mAnimator.removeCallback(displayId);
}

PointerControllerContext::PointerAnimator::PointerAnimator(PointerControllerContext& context)
      : mContext(context) {
    initializeDisplayEventReceiver();
}

void PointerControllerContext::PointerAnimator::initializeDisplayEventReceiver() {
    if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
        mContext.mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
                                Looper::EVENT_INPUT, mContext.mCallback, nullptr);
    } else {
        ALOGE("Failed to initialize DisplayEventReceiver.");
    }
}

void PointerControllerContext::PointerAnimator::addCallback(int32_t displayId,
                                                            std::function<bool(nsecs_t)> callback) {
    std::scoped_lock lock(mLock);
    mLocked.callbacks[displayId] = callback;
    startAnimationLocked();
}

void PointerControllerContext::PointerAnimator::removeCallback(int32_t displayId) {
    std::scoped_lock lock(mLock);
    auto it = mLocked.callbacks.find(displayId);
    if (it == mLocked.callbacks.end()) {
        return;
    }
    mLocked.callbacks.erase(it);
}

void PointerControllerContext::PointerAnimator::handleVsyncEvents() {
    bool gotVsync = false;
    ssize_t n;
    nsecs_t timestamp;
    DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
    while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
        for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
            if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                timestamp = buf[i].header.timestamp;
                gotVsync = true;
            }
        }
    }
    if (gotVsync) {
        std::scoped_lock lock(mLock);
        mLocked.animationPending = false;
        handleCallbacksLocked(timestamp);
    }
}

nsecs_t PointerControllerContext::PointerAnimator::getAnimationTimeLocked() REQUIRES(mLock) {
    return mLocked.animationTime;
}

void PointerControllerContext::PointerAnimator::startAnimationLocked() REQUIRES(mLock) {
    if (!mLocked.animationPending) {
        mLocked.animationPending = true;
        mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
        mDisplayEventReceiver.requestNextVsync();
    }
}

void PointerControllerContext::PointerAnimator::handleCallbacksLocked(nsecs_t timestamp)
        REQUIRES(mLock) {
    for (auto it = mLocked.callbacks.begin(); it != mLocked.callbacks.end();) {
        bool keepCallback = it->second(timestamp);
        if (!keepCallback) {
            it = mLocked.callbacks.erase(it);
        } else {
            ++it;
        }
    }

    if (!mLocked.callbacks.empty()) {
        startAnimationLocked();
    }
}

} // namespace android
