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

//#define LOG_NDEBUG 0
#undef LOG_TAG
#define LOG_TAG "FakeComposer"

#include "FakeComposerClient.h"

#include <gui/SurfaceComposerClient.h>

#include <log/log.h>

#include <gtest/gtest.h>

#include <inttypes.h>
#include <time.h>
#include <algorithm>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <set>
#include <thread>

constexpr Config NULL_DISPLAY_CONFIG = static_cast<Config>(0);

using namespace sftest;

using android::Condition;
using android::Mutex;

using Clock = std::chrono::steady_clock;
using TimePoint = std::chrono::time_point<Clock>;

namespace {

// Internal state of a layer in the HWC API.
class LayerImpl {
public:
    LayerImpl() = default;

    bool mValid = true;
    RenderState mRenderState;
    uint32_t mZ = 0;
};

// Struct for storing per frame rectangle state. Contains the render
// state shared to the test case. Basically a snapshot and a subset of
// LayerImpl sufficient to re-create the pixels of a layer for the
// frame.
struct FrameRect {
public:
    FrameRect(Layer layer_, const RenderState& state, uint32_t z_)
          : layer(layer_), renderState(state), z(z_) {}

    const Layer layer;
    const RenderState renderState;
    const uint32_t z;
};

// Collection of FrameRects forming one rendered frame. Could store
// related fences and other data in the future.
class Frame {
public:
    Frame() = default;
    std::vector<std::unique_ptr<FrameRect>> rectangles;
};

class DelayedEventGenerator {
public:
    DelayedEventGenerator(std::function<void()> onTimerExpired)
          : mOnTimerExpired(onTimerExpired), mThread([this]() { loop(); }) {}

    ~DelayedEventGenerator() {
        ALOGI("DelayedEventGenerator exiting.");
        {
            std::unique_lock<std::mutex> lock(mMutex);
            mRunning = false;
            mWakeups.clear();
            mCondition.notify_one();
        }
        mThread.join();
        ALOGI("DelayedEventGenerator exited.");
    }

    void wakeAfter(std::chrono::nanoseconds waitTime) {
        std::unique_lock<std::mutex> lock(mMutex);
        mWakeups.insert(Clock::now() + waitTime);
        mCondition.notify_one();
    }

private:
    void loop() {
        while (true) {
            // Lock scope
            {
                std::unique_lock<std::mutex> lock(mMutex);
                mCondition.wait(lock, [this]() { return !mRunning || !mWakeups.empty(); });
                if (!mRunning && mWakeups.empty()) {
                    // This thread should only exit once the destructor has been called and all
                    // wakeups have been processed
                    return;
                }

                // At this point, mWakeups will not be empty

                TimePoint target = *(mWakeups.begin());
                auto status = mCondition.wait_until(lock, target);
                while (status == std::cv_status::no_timeout) {
                    // This was either a spurious wakeup or another wakeup was added, so grab the
                    // oldest point and wait again
                    target = *(mWakeups.begin());
                    status = mCondition.wait_until(lock, target);
                }

                // status must have been timeout, so we can finally clear this point
                mWakeups.erase(target);
            }
            // Callback *without* locks!
            mOnTimerExpired();
        }
    }

    std::function<void()> mOnTimerExpired;
    std::thread mThread;
    std::mutex mMutex;
    std::condition_variable mCondition;
    bool mRunning = true;
    std::set<TimePoint> mWakeups;
};

} // namespace

FakeComposerClient::FakeComposerClient()
      : mEventCallback(nullptr),
        mCurrentConfig(NULL_DISPLAY_CONFIG),
        mVsyncEnabled(false),
        mLayers(),
        mDelayedEventGenerator(
                std::make_unique<DelayedEventGenerator>([this]() { this->requestVSync(); })),
        mSurfaceComposer(nullptr) {}

FakeComposerClient::~FakeComposerClient() {}

bool FakeComposerClient::hasCapability(hwc2_capability_t /*capability*/) {
    return false;
}

std::string FakeComposerClient::dumpDebugInfo() {
    return {};
}

void FakeComposerClient::registerEventCallback(EventCallback* callback) {
    ALOGV("registerEventCallback");
    mEventCallback = callback;
    if (mEventCallback) {
        mEventCallback->onHotplug(PRIMARY_DISPLAY, IComposerCallback::Connection::CONNECTED);
    }
}

void FakeComposerClient::unregisterEventCallback() {
    ALOGV("unregisterEventCallback");
    mEventCallback = nullptr;
}

void FakeComposerClient::hotplugDisplay(Display display, IComposerCallback::Connection state) {
    if (mEventCallback) {
        mEventCallback->onHotplug(display, state);
    }
}

void FakeComposerClient::refreshDisplay(Display display) {
    if (mEventCallback) {
        mEventCallback->onRefresh(display);
    }
}

uint32_t FakeComposerClient::getMaxVirtualDisplayCount() {
    ALOGV("getMaxVirtualDisplayCount");
    return 1;
}

Error FakeComposerClient::createVirtualDisplay(uint32_t /*width*/, uint32_t /*height*/,
                                               PixelFormat* /*format*/, Display* /*outDisplay*/) {
    ALOGV("createVirtualDisplay");
    return Error::NONE;
}

Error FakeComposerClient::destroyVirtualDisplay(Display /*display*/) {
    ALOGV("destroyVirtualDisplay");
    return Error::NONE;
}

Error FakeComposerClient::createLayer(Display /*display*/, Layer* outLayer) {
    ALOGV("createLayer");
    *outLayer = mLayers.size();
    auto newLayer = std::make_unique<LayerImpl>();
    mLayers.push_back(std::move(newLayer));
    return Error::NONE;
}

Error FakeComposerClient::destroyLayer(Display /*display*/, Layer layer) {
    ALOGV("destroyLayer");
    mLayers[layer]->mValid = false;
    return Error::NONE;
}

Error FakeComposerClient::getActiveConfig(Display /*display*/, Config* outConfig) {
    ALOGV("getActiveConfig");

    // TODO Assert outConfig != nullptr

    // TODO This is my reading of the
    // IComposerClient::getActiveConfig, but returning BAD_CONFIG
    // seems to not fit SurfaceFlinger plans. See version 2 below.
    // if (mCurrentConfig == NULL_DISPLAY_CONFIG) {
    //     return Error::BAD_CONFIG;
    // }
    //*outConfig = mCurrentConfig;
    *outConfig = 1; // Very special config for you my friend
    return Error::NONE;
}

Error FakeComposerClient::getClientTargetSupport(Display /*display*/, uint32_t /*width*/,
                                                 uint32_t /*height*/, PixelFormat /*format*/,
                                                 Dataspace /*dataspace*/) {
    ALOGV("getClientTargetSupport");
    return Error::NONE;
}

Error FakeComposerClient::getColorModes(Display /*display*/, hidl_vec<ColorMode>* /*outModes*/) {
    ALOGV("getColorModes");
    return Error::NONE;
}

Error FakeComposerClient::getDisplayAttribute(Display display, Config config,
                                              IComposerClient::Attribute attribute,
                                              int32_t* outValue) {
    ALOGV("getDisplayAttribute (%d, %d, %d, %p)", static_cast<int>(display),
          static_cast<int>(config), static_cast<int>(attribute), outValue);

    // TODO: SOOO much fun to be had with these alone
    switch (attribute) {
        case IComposerClient::Attribute::WIDTH:
            *outValue = 1920;
            break;
        case IComposerClient::Attribute::HEIGHT:
            *outValue = 1080;
            break;
        case IComposerClient::Attribute::VSYNC_PERIOD:
            *outValue = 1666666666;
            break; // TOOD: Tests break down if lowered to 16ms?
        case IComposerClient::Attribute::DPI_X:
            *outValue = 240;
            break;
        case IComposerClient::Attribute::DPI_Y:
            *outValue = 240;
            break;
        default:
            LOG_ALWAYS_FATAL("Say what!?! New attribute");
    }

    return Error::NONE;
}

Error FakeComposerClient::getDisplayConfigs(Display /*display*/, hidl_vec<Config>* outConfigs) {
    ALOGV("getDisplayConfigs");
    // TODO assert display == 1, outConfigs != nullptr

    outConfigs->resize(1);
    (*outConfigs)[0] = 1;

    return Error::NONE;
}

Error FakeComposerClient::getDisplayName(Display /*display*/, hidl_string* /*outName*/) {
    ALOGV("getDisplayName");
    return Error::NONE;
}

Error FakeComposerClient::getDisplayType(Display /*display*/,
                                         IComposerClient::DisplayType* outType) {
    ALOGV("getDisplayType");
    // TODO: This setting nothing on the output had no effect on initial trials. Is first display
    // assumed to be physical?
    *outType = static_cast<IComposerClient::DisplayType>(HWC2_DISPLAY_TYPE_PHYSICAL);
    return Error::NONE;
}

Error FakeComposerClient::getDozeSupport(Display /*display*/, bool* /*outSupport*/) {
    ALOGV("getDozeSupport");
    return Error::NONE;
}

Error FakeComposerClient::getHdrCapabilities(Display /*display*/, hidl_vec<Hdr>* /*outTypes*/,
                                             float* /*outMaxLuminance*/,
                                             float* /*outMaxAverageLuminance*/,
                                             float* /*outMinLuminance*/) {
    ALOGV("getHdrCapabilities");
    return Error::NONE;
}

Error FakeComposerClient::setActiveConfig(Display /*display*/, Config config) {
    ALOGV("setActiveConfig");
    mCurrentConfig = config;
    return Error::NONE;
}

Error FakeComposerClient::setColorMode(Display /*display*/, ColorMode /*mode*/) {
    ALOGV("setColorMode");
    return Error::NONE;
}

Error FakeComposerClient::setPowerMode(Display /*display*/, IComposerClient::PowerMode /*mode*/) {
    ALOGV("setPowerMode");
    return Error::NONE;
}

Error FakeComposerClient::setVsyncEnabled(Display /*display*/, IComposerClient::Vsync enabled) {
    mVsyncEnabled = (enabled == IComposerClient::Vsync::ENABLE);
    ALOGV("setVsyncEnabled(%s)", mVsyncEnabled ? "ENABLE" : "DISABLE");
    return Error::NONE;
}

Error FakeComposerClient::setColorTransform(Display /*display*/, const float* /*matrix*/,
                                            int32_t /*hint*/) {
    ALOGV("setColorTransform");
    return Error::NONE;
}

Error FakeComposerClient::setClientTarget(Display /*display*/, buffer_handle_t /*target*/,
                                          int32_t /*acquireFence*/, int32_t /*dataspace*/,
                                          const std::vector<hwc_rect_t>& /*damage*/) {
    ALOGV("setClientTarget");
    return Error::NONE;
}

Error FakeComposerClient::setOutputBuffer(Display /*display*/, buffer_handle_t /*buffer*/,
                                          int32_t /*releaseFence*/) {
    ALOGV("setOutputBuffer");
    return Error::NONE;
}

Error FakeComposerClient::validateDisplay(
        Display /*display*/, std::vector<Layer>* /*outChangedLayers*/,
        std::vector<IComposerClient::Composition>* /*outCompositionTypes*/,
        uint32_t* /*outDisplayRequestMask*/, std::vector<Layer>* /*outRequestedLayers*/,
        std::vector<uint32_t>* /*outRequestMasks*/) {
    ALOGV("validateDisplay");
    // TODO: Assume touching nothing means All Korrekt!
    return Error::NONE;
}

Error FakeComposerClient::acceptDisplayChanges(Display /*display*/) {
    ALOGV("acceptDisplayChanges");
    // Didn't ask for changes because software is omnipotent.
    return Error::NONE;
}

bool layerZOrdering(const std::unique_ptr<FrameRect>& a, const std::unique_ptr<FrameRect>& b) {
    return a->z <= b->z;
}

Error FakeComposerClient::presentDisplay(Display /*display*/, int32_t* /*outPresentFence*/,
                                         std::vector<Layer>* /*outLayers*/,
                                         std::vector<int32_t>* /*outReleaseFences*/) {
    ALOGV("presentDisplay");
    // TODO Leaving layers and their fences out for now. Doing so
    // means that we've already processed everything. Important to
    // test that the fences are respected, though. (How?)

    std::unique_ptr<Frame> newFrame(new Frame);
    for (uint64_t layer = 0; layer < mLayers.size(); layer++) {
        const LayerImpl& layerImpl = *mLayers[layer];

        if (!layerImpl.mValid) continue;

        auto rect = std::make_unique<FrameRect>(layer, layerImpl.mRenderState, layerImpl.mZ);
        newFrame->rectangles.push_back(std::move(rect));
    }
    std::sort(newFrame->rectangles.begin(), newFrame->rectangles.end(), layerZOrdering);
    {
        Mutex::Autolock _l(mStateMutex);
        mFrames.push_back(std::move(newFrame));
        mFramesAvailable.broadcast();
    }
    return Error::NONE;
}

Error FakeComposerClient::setLayerCursorPosition(Display /*display*/, Layer /*layer*/,
                                                 int32_t /*x*/, int32_t /*y*/) {
    ALOGV("setLayerCursorPosition");
    return Error::NONE;
}

Error FakeComposerClient::setLayerBuffer(Display /*display*/, Layer layer, buffer_handle_t buffer,
                                         int32_t acquireFence) {
    ALOGV("setLayerBuffer");
    LayerImpl& l = getLayerImpl(layer);
    if (buffer != l.mRenderState.mBuffer) {
        l.mRenderState.mSwapCount++; // TODO: Is setting to same value a swap or not?
    }
    l.mRenderState.mBuffer = buffer;
    l.mRenderState.mAcquireFence = acquireFence;

    return Error::NONE;
}

Error FakeComposerClient::setLayerSurfaceDamage(Display /*display*/, Layer /*layer*/,
                                                const std::vector<hwc_rect_t>& /*damage*/) {
    ALOGV("setLayerSurfaceDamage");
    return Error::NONE;
}

Error FakeComposerClient::setLayerBlendMode(Display /*display*/, Layer layer, int32_t mode) {
    ALOGV("setLayerBlendMode");
    getLayerImpl(layer).mRenderState.mBlendMode = static_cast<hwc2_blend_mode_t>(mode);
    return Error::NONE;
}

Error FakeComposerClient::setLayerColor(Display /*display*/, Layer layer,
                                        IComposerClient::Color color) {
    ALOGV("setLayerColor");
    getLayerImpl(layer).mRenderState.mLayerColor.r = color.r;
    getLayerImpl(layer).mRenderState.mLayerColor.g = color.g;
    getLayerImpl(layer).mRenderState.mLayerColor.b = color.b;
    getLayerImpl(layer).mRenderState.mLayerColor.a = color.a;
    return Error::NONE;
}

Error FakeComposerClient::setLayerCompositionType(Display /*display*/, Layer /*layer*/,
                                                  int32_t /*type*/) {
    ALOGV("setLayerCompositionType");
    return Error::NONE;
}

Error FakeComposerClient::setLayerDataspace(Display /*display*/, Layer /*layer*/,
                                            int32_t /*dataspace*/) {
    ALOGV("setLayerDataspace");
    return Error::NONE;
}

Error FakeComposerClient::setLayerDisplayFrame(Display /*display*/, Layer layer,
                                               const hwc_rect_t& frame) {
    ALOGV("setLayerDisplayFrame (%d, %d, %d, %d)", frame.left, frame.top, frame.right,
          frame.bottom);
    getLayerImpl(layer).mRenderState.mDisplayFrame = frame;
    return Error::NONE;
}

Error FakeComposerClient::setLayerPlaneAlpha(Display /*display*/, Layer layer, float alpha) {
    ALOGV("setLayerPlaneAlpha");
    getLayerImpl(layer).mRenderState.mPlaneAlpha = alpha;
    return Error::NONE;
}

Error FakeComposerClient::setLayerSidebandStream(Display /*display*/, Layer /*layer*/,
                                                 buffer_handle_t /*stream*/) {
    ALOGV("setLayerSidebandStream");
    return Error::NONE;
}

Error FakeComposerClient::setLayerSourceCrop(Display /*display*/, Layer layer,
                                             const hwc_frect_t& crop) {
    ALOGV("setLayerSourceCrop");
    getLayerImpl(layer).mRenderState.mSourceCrop = crop;
    return Error::NONE;
}

Error FakeComposerClient::setLayerTransform(Display /*display*/, Layer layer, int32_t transform) {
    ALOGV("setLayerTransform");
    getLayerImpl(layer).mRenderState.mTransform = static_cast<hwc_transform_t>(transform);
    return Error::NONE;
}

Error FakeComposerClient::setLayerVisibleRegion(Display /*display*/, Layer layer,
                                                const std::vector<hwc_rect_t>& visible) {
    ALOGV("setLayerVisibleRegion");
    getLayerImpl(layer).mRenderState.mVisibleRegion = visible;
    return Error::NONE;
}

Error FakeComposerClient::setLayerZOrder(Display /*display*/, Layer layer, uint32_t z) {
    ALOGV("setLayerZOrder");
    getLayerImpl(layer).mZ = z;
    return Error::NONE;
}

//////////////////////////////////////////////////////////////////

void FakeComposerClient::requestVSync(uint64_t vsyncTime) {
    if (mEventCallback) {
        uint64_t timestamp = vsyncTime;
        ALOGV("Vsync");
        if (timestamp == 0) {
            struct timespec ts;
            clock_gettime(CLOCK_MONOTONIC, &ts);
            timestamp = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
        }
        if (mSurfaceComposer != nullptr) {
            mSurfaceComposer->injectVSync(timestamp);
        } else {
            mEventCallback->onVsync(PRIMARY_DISPLAY, timestamp);
        }
    }
}

void FakeComposerClient::runVSyncAfter(std::chrono::nanoseconds wait) {
    mDelayedEventGenerator->wakeAfter(wait);
}

LayerImpl& FakeComposerClient::getLayerImpl(Layer handle) {
    // TODO Change these to an internal state check that can be
    // invoked from the gtest? GTest macros do not seem all that safe
    // when used outside the test class
    EXPECT_GE(handle, static_cast<Layer>(0));
    EXPECT_LT(handle, mLayers.size());
    return *(mLayers[handle]);
}

int FakeComposerClient::getFrameCount() const {
    return mFrames.size();
}

static std::vector<RenderState> extractRenderState(
        const std::vector<std::unique_ptr<FrameRect>>& internalRects) {
    std::vector<RenderState> result;
    result.reserve(internalRects.size());
    for (const std::unique_ptr<FrameRect>& rect : internalRects) {
        result.push_back(rect->renderState);
    }
    return result;
}

std::vector<RenderState> FakeComposerClient::getFrameRects(int frame) const {
    Mutex::Autolock _l(mStateMutex);
    return extractRenderState(mFrames[frame]->rectangles);
}

std::vector<RenderState> FakeComposerClient::getLatestFrame() const {
    Mutex::Autolock _l(mStateMutex);
    return extractRenderState(mFrames[mFrames.size() - 1]->rectangles);
}

void FakeComposerClient::runVSyncAndWait(std::chrono::nanoseconds maxWait) {
    int currentFrame = 0;
    {
        Mutex::Autolock _l(mStateMutex); // I hope this is ok...
        currentFrame = static_cast<int>(mFrames.size());
        requestVSync();
    }
    waitUntilFrame(currentFrame + 1, maxWait);
}

void FakeComposerClient::waitUntilFrame(int targetFrame, std::chrono::nanoseconds maxWait) const {
    Mutex::Autolock _l(mStateMutex);
    while (mFrames.size() < static_cast<size_t>(targetFrame)) {
        android::status_t result = mFramesAvailable.waitRelative(mStateMutex, maxWait.count());
        if (result == android::TIMED_OUT) {
            ALOGE("Waiting for frame %d (at frame %zu now) timed out after %lld ns", targetFrame,
                  mFrames.size(), maxWait.count());
            return;
        }
    }
}

void FakeComposerClient::clearFrames() {
    Mutex::Autolock _l(mStateMutex);
    mFrames.clear();
    for (const std::unique_ptr<LayerImpl>& layer : mLayers) {
        if (layer->mValid) {
            layer->mRenderState.mSwapCount = 0;
        }
    }
}

void FakeComposerClient::onSurfaceFlingerStart() {
    mSurfaceComposer = nullptr;
    do {
        mSurfaceComposer = new android::SurfaceComposerClient;
        android::status_t initResult = mSurfaceComposer->initCheck();
        if (initResult != android::NO_ERROR) {
            ALOGD("Init result: %d", initResult);
            mSurfaceComposer = nullptr;
            std::this_thread::sleep_for(10ms);
        }
    } while (mSurfaceComposer == nullptr);
    ALOGD("SurfaceComposerClient created");
    mSurfaceComposer->enableVSyncInjections(true);
}

void FakeComposerClient::onSurfaceFlingerStop() {
    mSurfaceComposer->dispose();
    mSurfaceComposer.clear();
}

// Includes destroyed layers, stored in order of creation.
int FakeComposerClient::getLayerCount() const {
    return mLayers.size();
}

Layer FakeComposerClient::getLayer(size_t index) const {
    // NOTE: If/when passing calls through to actual implementation,
    // this might get more involving.
    return static_cast<Layer>(index);
}
