/*
 * Copyright 2018 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.
 */

// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"

#include <gui/BufferItemConsumer.h>
#include <gui/Surface.h>

#include <GLES3/gl3.h>
#include <math/vec2.h>
#include <math/vec3.h>
#include <math/vec4.h>

#include "BufferGenerator.h"
#include "BufferGeneratorShader.h"

namespace android {

/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
 * away. The fences are sent to the requester via a callback */
class SurfaceManager {
public:
    /* Returns a fence from egl */
    using BufferCallback = std::function<void(const sp<GraphicBuffer>& buffer, int32_t fence)>;

    /* Listens for a new frame, detaches the buffer and returns the fence
     * through saved callback. */
    class BufferListener : public ConsumerBase::FrameAvailableListener {
    public:
        BufferListener(sp<IGraphicBufferConsumer> consumer, BufferCallback callback)
              : mConsumer(consumer), mCallback(callback) {}

        void onFrameAvailable(const BufferItem& /*item*/) {
            BufferItem item;

            if (mConsumer->acquireBuffer(&item, 0)) return;
            if (mConsumer->detachBuffer(item.mSlot)) return;

            mCallback(item.mGraphicBuffer, item.mFence->dup());
        }

    private:
        sp<IGraphicBufferConsumer> mConsumer;
        BufferCallback mCallback;
    };

    /* Creates a buffer listener that waits on a new frame from the buffer
     * queue. */
    void initialize(uint32_t width, uint32_t height, android_pixel_format_t format,
                    BufferCallback callback) {
        sp<IGraphicBufferProducer> producer;
        sp<IGraphicBufferConsumer> consumer;
        BufferQueue::createBufferQueue(&producer, &consumer);

        consumer->setDefaultBufferSize(width, height);
        consumer->setDefaultBufferFormat(format);

        mBufferItemConsumer = new BufferItemConsumer(consumer, 0);

        mListener = new BufferListener(consumer, callback);
        mBufferItemConsumer->setFrameAvailableListener(mListener);

        mSurface = new Surface(producer, true);
    }

    /* Used by Egl manager. The surface is never displayed. */
    sp<Surface> getSurface() const { return mSurface; }

private:
    sp<BufferItemConsumer> mBufferItemConsumer;
    sp<BufferListener> mListener;
    /* Used by Egl manager. The surface is never displayed */
    sp<Surface> mSurface;
};

/* Used to generate valid fences. It is not possible to create a dummy sync
 * fence for testing. Egl can generate buffers along with a valid fence.
 * The buffer cannot be guaranteed to be the same format across all devices so
 * a CPU filled buffer is used instead. The Egl fence is used along with the
 * CPU filled buffer. */
class EglManager {
public:
    EglManager()
          : mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE), mEglContext(EGL_NO_CONTEXT) {}

    ~EglManager() { cleanup(); }

    int initialize(sp<Surface> surface) {
        mSurface = surface;

        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        if (mEglDisplay == EGL_NO_DISPLAY) return false;

        EGLint major;
        EGLint minor;
        if (!eglInitialize(mEglDisplay, &major, &minor)) {
            ALOGW("Could not initialize EGL");
            return false;
        }

        /* We're going to use a 1x1 pbuffer surface later on
         * The configuration distance doesn't really matter for what we're
         * trying to do */
        EGLint configAttrs[] = {EGL_RENDERABLE_TYPE,
                                EGL_OPENGL_ES2_BIT,
                                EGL_RED_SIZE,
                                8,
                                EGL_GREEN_SIZE,
                                8,
                                EGL_BLUE_SIZE,
                                8,
                                EGL_ALPHA_SIZE,
                                0,
                                EGL_DEPTH_SIZE,
                                24,
                                EGL_STENCIL_SIZE,
                                0,
                                EGL_NONE};

        EGLConfig configs[1];
        EGLint configCnt;
        if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1, &configCnt)) {
            ALOGW("Could not select EGL configuration");
            eglReleaseThread();
            eglTerminate(mEglDisplay);
            return false;
        }

        if (configCnt <= 0) {
            ALOGW("Could not find EGL configuration");
            eglReleaseThread();
            eglTerminate(mEglDisplay);
            return false;
        }

        /* These objects are initialized below but the default "null" values are
         * used to cleanup properly at any point in the initialization sequence */
        EGLint attrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
        mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT, attrs);
        if (mEglContext == EGL_NO_CONTEXT) {
            ALOGW("Could not create EGL context");
            cleanup();
            return false;
        }

        EGLint majorVersion;
        if (!eglQueryContext(mEglDisplay, mEglContext, EGL_CONTEXT_CLIENT_VERSION, &majorVersion)) {
            ALOGW("Could not query EGL version");
            cleanup();
            return false;
        }

        if (majorVersion != 3) {
            ALOGW("Unsupported EGL version");
            cleanup();
            return false;
        }

        EGLint surfaceAttrs[] = {EGL_NONE};
        mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0], mSurface.get(), surfaceAttrs);
        if (mEglSurface == EGL_NO_SURFACE) {
            ALOGW("Could not create EGL surface");
            cleanup();
            return false;
        }

        if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
            ALOGW("Could not change current EGL context");
            cleanup();
            return false;
        }

        return true;
    }

    void makeCurrent() const { eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); }

    void present() const { eglSwapBuffers(mEglDisplay, mEglSurface); }

private:
    void cleanup() {
        if (mEglDisplay == EGL_NO_DISPLAY) return;
        if (mEglSurface != EGL_NO_SURFACE) eglDestroySurface(mEglDisplay, mEglSurface);
        if (mEglContext != EGL_NO_CONTEXT) eglDestroyContext(mEglDisplay, mEglContext);

        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        eglReleaseThread();
        eglTerminate(mEglDisplay);
    }

    sp<Surface> mSurface;
    EGLDisplay mEglDisplay;
    EGLSurface mEglSurface;
    EGLContext mEglContext;
};

class Program {
public:
    ~Program() {
        if (mInitialized) {
            glDetachShader(mProgram, mVertexShader);
            glDetachShader(mProgram, mFragmentShader);

            glDeleteShader(mVertexShader);
            glDeleteShader(mFragmentShader);

            glDeleteProgram(mProgram);
        }
    }

    bool initialize(const char* vertex, const char* fragment) {
        mVertexShader = buildShader(vertex, GL_VERTEX_SHADER);
        if (!mVertexShader) {
            return false;
        }

        mFragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
        if (!mFragmentShader) {
            return false;
        }

        mProgram = glCreateProgram();
        glAttachShader(mProgram, mVertexShader);
        glAttachShader(mProgram, mFragmentShader);

        glLinkProgram(mProgram);

        GLint status;
        glGetProgramiv(mProgram, GL_LINK_STATUS, &status);
        if (status != GL_TRUE) {
            GLint length = 0;
            glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &length);
            if (length > 1) {
                GLchar log[length];
                glGetProgramInfoLog(mProgram, length, nullptr, &log[0]);
                ALOGE("%s", log);
            }
            ALOGE("Error while linking shaders");
            return false;
        }
        mInitialized = true;
        return true;
    }

    void use() const { glUseProgram(mProgram); }

    void bindVec4(GLint location, vec4 v) const { glUniform4f(location, v.x, v.y, v.z, v.w); }

    void bindVec3(GLint location, const vec3* v, uint32_t count) const {
        glUniform3fv(location, count, &(v->x));
    }

    void bindFloat(GLint location, float v) { glUniform1f(location, v); }

private:
    GLuint buildShader(const char* source, GLenum type) const {
        GLuint shader = glCreateShader(type);
        glShaderSource(shader, 1, &source, nullptr);
        glCompileShader(shader);

        GLint status;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
        if (status != GL_TRUE) {
            ALOGE("Error while compiling shader of type 0x%x:\n===\n%s\n===", type, source);
            // Some drivers return wrong values for GL_INFO_LOG_LENGTH
            // use a fixed size instead
            GLchar log[512];
            glGetShaderInfoLog(shader, sizeof(log), nullptr, &log[0]);
            ALOGE("Shader info log: %s", log);
            return 0;
        }

        return shader;
    }

    GLuint mProgram = 0;
    GLuint mVertexShader = 0;
    GLuint mFragmentShader = 0;
    bool mInitialized = false;
};

BufferGenerator::BufferGenerator()
      : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) {
    const float width = 1000.0;
    const float height = 1000.0;

    auto setBufferWithContext =
            std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this);
    mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext);

    if (!mEglManager->initialize(mSurfaceManager->getSurface())) return;

    mEglManager->makeCurrent();

    if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return;
    mProgram->use();
    mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height});
    mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &TRIANGLE[0]);

    mInitialized = true;
}

BufferGenerator::~BufferGenerator() {
    mEglManager->makeCurrent();
}

status_t BufferGenerator::get(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
    // mMutex is used to protect get() from getting called by multiple threads at the same time
    static std::mutex mMutex;
    std::lock_guard lock(mMutex);

    if (!mInitialized) {
        if (outBuffer) {
            *outBuffer = nullptr;
        }
        if (*outFence) {
            *outFence = nullptr;
        }
        return -EINVAL;
    }

    // Generate a buffer and fence. They will be returned through the setBuffer callback
    mEglManager->makeCurrent();

    glClear(GL_COLOR_BUFFER_BIT);

    const std::chrono::duration<float> time = std::chrono::steady_clock::now() - mEpoch;
    mProgram->bindFloat(1, time.count());

    glDrawArrays(GL_TRIANGLES, 0, 3);

    mPending = true;
    mEglManager->present();

    // Wait for the setBuffer callback
    if (!mConditionVariable.wait_for(mMutex, std::chrono::seconds(2),
                                     [this] { return !mPending; })) {
        ALOGE("failed to set buffer and fence");
        return -ETIME;
    }

    // Return buffer and fence
    if (outBuffer) {
        *outBuffer = mGraphicBuffer;
    }
    if (outFence) {
        *outFence = new Fence(mFence);
    } else {
        close(mFence);
    }
    mGraphicBuffer = nullptr;
    mFence = -1;

    return NO_ERROR;
}

// static
void BufferGenerator::setBuffer(const sp<GraphicBuffer>& buffer, int32_t fence,
                                void* bufferGenerator) {
    BufferGenerator* generator = static_cast<BufferGenerator*>(bufferGenerator);
    generator->mGraphicBuffer = buffer;
    generator->mFence = fence;
    generator->mPending = false;
    generator->mConditionVariable.notify_all();
}

} // namespace android

// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
