/*
 * 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);
constexpr Display DEFAULT_DISPLAY = static_cast<Display>(1);

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()
      : mCallbacksOn(false),
        mClient(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;
}

void FakeComposerClient::removeClient() {
    ALOGV("removeClient");
    // TODO: Ahooga! Only thing current lifetime management choices in
    // APIs make possible. Sad.
    delete this;
}

void FakeComposerClient::enableCallback(bool enable) {
    ALOGV("enableCallback");
    mCallbacksOn = enable;
    if (mCallbacksOn) {
        mClient->onHotplug(DEFAULT_DISPLAY, IComposerCallback::Connection::CONNECTED);
    }
}

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

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::setClient(ComposerClient* client) {
    mClient = client;
}

void FakeComposerClient::requestVSync(uint64_t vsyncTime) {
    if (mCallbacksOn) {
        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 {
            mClient->onVsync(DEFAULT_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);
}
