// Copyright 2014-2015 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 "RenderWindow.h"

#include "emugl/common/logging.h"
#include "emugl/common/message_channel.h"
#include "emugl/common/mutex.h"
#include "emugl/common/thread.h"
#include "FrameBuffer.h"

#include <stdarg.h>
#include <stdio.h>
#ifndef _WIN32
#include <signal.h>
#include <pthread.h>
#endif

#define DEBUG 0

#if DEBUG
#  define D(...) my_debug(__PRETTY_FUNCTION__, __LINE__, __VA_ARGS__)
#else
#  define D(...) ((void)0)
#endif

namespace {

#if DEBUG
void my_debug(const char* function, int line, const char* format, ...) {
    static ::emugl::Mutex mutex;
    va_list args;
    va_start(args, format);
    mutex.lock();
    fprintf(stderr, "%s:%d:", function, line);
    vfprintf(stderr, format, args);
    mutex.unlock();
    va_end(args);
}
#endif

// List of possible commands to send to the render window thread from
// the main one.
enum Command {
    CMD_INITIALIZE,
    CMD_SET_POST_CALLBACK,
    CMD_SETUP_SUBWINDOW,
    CMD_REMOVE_SUBWINDOW,
    CMD_SET_ROTATION,
    CMD_SET_TRANSLATION,
    CMD_REPAINT,
    CMD_FINALIZE,
};

}  // namespace

// A single message sent from the main thread to the render window thread.
// |cmd| determines which fields are valid to read.
struct RenderWindowMessage {
    Command cmd;
    union {
        // CMD_INITIALIZE
        struct {
            int width;
            int height;
            bool useSubWindow;
        } init;

        // CMD_SET_POST_CALLBACK
        struct {
            emugl::Renderer::OnPostCallback on_post;
            void* on_post_context;
        } set_post_callback;

        // CMD_SETUP_SUBWINDOW
        struct {
            FBNativeWindowType parent;
            int wx;
            int wy;
            int ww;
            int wh;
            int fbw;
            int fbh;
            float dpr;
            float rotation;
        } subwindow;

        // CMD_SET_TRANSLATION;
        struct {
            float px;
            float py;
        } trans;

        // CMD_SET_ROTATION
        float rotation;

        // result of operations.
        bool result;
    };

    // Process the current message, and updates its |result| field.
    // Returns true on success, or false on failure.
    bool process() const {
        const RenderWindowMessage& msg = *this;
        FrameBuffer* fb;
        bool result = false;
        switch (msg.cmd) {
            case CMD_INITIALIZE:
                D("CMD_INITIALIZE w=%d h=%d\n", msg.init.width, msg.init.height);
                GL_LOG("RenderWindow: CMD_INITIALIZE w=%d h=%d",
                       msg.init.width, msg.init.height);
                result = FrameBuffer::initialize(msg.init.width,
                                                 msg.init.height,
                                                 msg.init.useSubWindow);
                break;

            case CMD_FINALIZE:
                D("CMD_FINALIZE\n");
                // this command may be issued even when frame buffer is not
                // yet created (e.g. if CMD_INITIALIZE failed),
                // so make sure we check if it is there before finalizing
                if (const auto fb = FrameBuffer::getFB()) {
                    fb->finalize();
                }
                result = true;
                break;

            case CMD_SET_POST_CALLBACK:
                D("CMD_SET_POST_CALLBACK\n");
                fb = FrameBuffer::getFB();
                fb->setPostCallback(msg.set_post_callback.on_post,
                                    msg.set_post_callback.on_post_context);
                result = true;
                break;

            case CMD_SETUP_SUBWINDOW:
                D("CMD_SETUP_SUBWINDOW: parent=%p wx=%d wy=%d ww=%d wh=%d fbw=%d fbh=%d dpr=%f rotation=%f\n",
                    (void*)msg.subwindow.parent,
                    msg.subwindow.wx,
                    msg.subwindow.wy,
                    msg.subwindow.ww,
                    msg.subwindow.wh,
                    msg.subwindow.fbw,
                    msg.subwindow.fbh,
                    msg.subwindow.dpr,
                    msg.subwindow.rotation);
                result = FrameBuffer::getFB()->setupSubWindow(
                        msg.subwindow.parent,
                        msg.subwindow.wx,
                        msg.subwindow.wy,
                        msg.subwindow.ww,
                        msg.subwindow.wh,
                        msg.subwindow.fbw,
                        msg.subwindow.fbh,
                        msg.subwindow.dpr,
                        msg.subwindow.rotation);
                break;

            case CMD_REMOVE_SUBWINDOW:
                D("CMD_REMOVE_SUBWINDOW\n");
                result = FrameBuffer::getFB()->removeSubWindow();
                break;

            case CMD_SET_ROTATION:
                D("CMD_SET_ROTATION rotation=%f\n", msg.rotation);
                fb = FrameBuffer::getFB();
                if (fb) {
                    fb->setDisplayRotation(msg.rotation);
                    result = true;
                }
                break;

            case CMD_SET_TRANSLATION:
                D("CMD_SET_TRANSLATION translation=%f,%f\n", msg.trans.px, msg.trans.py);
                fb = FrameBuffer::getFB();
                if (fb) {
                    fb->setDisplayTranslation(msg.trans.px, msg.trans.py);
                    result = true;
                }
                break;

            case CMD_REPAINT:
                D("CMD_REPAINT\n");
                fb = FrameBuffer::getFB();
                if (fb) {
                    fb->repost();
                    result = true;
                }
                break;

            default:
                ;
        }
        return result;
    }
};

// Simple synchronization structure used to exchange data between the
// main and render window threads. Usage is the following:
//
// The main thread does the following in a loop:
//
//      canWriteCmd.wait()
//      updates |message| by writing a new |cmd| value and appropriate
//      parameters.
//      canReadCmd.signal()
//      canReadResult.wait()
//      reads |message.result|
//      canWriteResult.signal()
//
// The render window thread will do the following:
//
//      canReadCmd.wait()
//      reads |message.cmd| and acts upon it.
//      canWriteResult.wait()
//      writes |message.result|
//      canReadResult.signal()
//      canWriteCmd.signal()
//
class RenderWindowChannel {
public:
    RenderWindowChannel() : mIn(), mOut() {}
    ~RenderWindowChannel() {}

    // Send a message from the main thread.
    // Note that the content of |msg| is copied into the channel.
    // Returns with the command's result (true or false).
    bool sendMessageAndGetResult(const RenderWindowMessage& msg) {
        D("msg.cmd=%d\n", msg.cmd);
        mIn.send(msg);
        D("waiting for result\n");
        bool result = false;
        mOut.receive(&result);
        D("result=%s\n", result ? "success" : "failure");
        return result;
    }

    // Receive a message from the render window thread.
    // On exit, |*msg| gets a copy of the message. The caller
    // must always call sendResult() after processing the message.
    void receiveMessage(RenderWindowMessage* msg) {
        D("entering\n");
        mIn.receive(msg);
        D("message cmd=%d\n", msg->cmd);
    }

    // Send result from the render window thread to the main one.
    // Must always be called after receiveMessage().
    void sendResult(bool result) {
        D("waiting to send result (%s)\n", result ? "success" : "failure");
        mOut.send(result);
        D("result sent\n");
    }

private:
    emugl::MessageChannel<RenderWindowMessage, 16U> mIn;
    emugl::MessageChannel<bool, 16U> mOut;
};

namespace {

// This class implements the window render thread.
// Its purpose is to listen for commands from the main thread in a loop,
// process them, then return a boolean result for each one of them.
//
// The thread ends with a CMD_FINALIZE.
//
class RenderWindowThread : public emugl::Thread {
public:
    RenderWindowThread(RenderWindowChannel* channel) : mChannel(channel) {}

    virtual intptr_t main() {
        D("Entering render window thread thread\n");
#ifndef _WIN32
        sigset_t set;
        sigfillset(&set);
        pthread_sigmask(SIG_SETMASK, &set, NULL);
#endif
        bool running = true;
        while (running) {
            RenderWindowMessage msg = {};

            D("Waiting for message from main thread\n");
            mChannel->receiveMessage(&msg);

            bool result = msg.process();
            if (msg.cmd == CMD_FINALIZE) {
                running = false;
            }

            D("Sending result (%s) to main thread\n", result ? "success" : "failure");
            mChannel->sendResult(result);
        }
        D("Exiting thread\n");
        return 0;
    }

private:
    RenderWindowChannel* mChannel;
};

}  // namespace

RenderWindow::RenderWindow(int width,
                           int height,
                           bool use_thread,
                           bool use_sub_window) {
    if (use_thread) {
        mChannel = new RenderWindowChannel();
        mThread = new RenderWindowThread(mChannel);
        mThread->start();
    }

    RenderWindowMessage msg = {};
    msg.cmd = CMD_INITIALIZE;
    msg.init.width = width;
    msg.init.height = height;
    msg.init.useSubWindow = use_sub_window;
    mValid = processMessage(msg);
}

RenderWindow::~RenderWindow() {
    D("Entering\n");
    removeSubWindow();
    D("Sending CMD_FINALIZE\n");
    RenderWindowMessage msg = {};
    msg.cmd = CMD_FINALIZE;
    (void) processMessage(msg);

    if (mThread) {
        mThread->wait(NULL);
        delete mThread;
        delete mChannel;
    }
}

bool RenderWindow::getHardwareStrings(const char** vendor,
                                      const char** renderer,
                                      const char** version) {
    D("Entering\n");
    // TODO(digit): Move this to render window thread.
    FrameBuffer* fb = FrameBuffer::getFB();
    if (!fb) {
        D("No framebuffer!\n");
        return false;
    }
    fb->getGLStrings(vendor, renderer, version);
    D("Exiting vendor=[%s] renderer=[%s] version=[%s]\n",
      *vendor, *renderer, *version);

    return true;
}

void RenderWindow::setPostCallback(emugl::Renderer::OnPostCallback onPost, void* onPostContext) {
    D("Entering\n");
    RenderWindowMessage msg = {};
    msg.cmd = CMD_SET_POST_CALLBACK;
    msg.set_post_callback.on_post = onPost;
    msg.set_post_callback.on_post_context = onPostContext;
    (void) processMessage(msg);
    D("Exiting\n");
}

bool RenderWindow::setupSubWindow(FBNativeWindowType window,
                                  int wx,
                                  int wy,
                                  int ww,
                                  int wh,
                                  int fbw,
                                  int fbh,
                                  float dpr,
                                  float zRot) {
    D("Entering mHasSubWindow=%s\n", mHasSubWindow ? "true" : "false");

    RenderWindowMessage msg = {};
    msg.cmd = CMD_SETUP_SUBWINDOW;
    msg.subwindow.parent = window;
    msg.subwindow.wx = wx;
    msg.subwindow.wy = wy;
    msg.subwindow.ww = ww;
    msg.subwindow.wh = wh;
    msg.subwindow.fbw = fbw;
    msg.subwindow.fbh = fbh;
    msg.subwindow.dpr = dpr;
    msg.subwindow.rotation = zRot;

    mHasSubWindow = processMessage(msg);
    D("Exiting mHasSubWindow=%s\n", mHasSubWindow ? "true" : "false");
    return mHasSubWindow;
}

bool RenderWindow::removeSubWindow() {
    D("Entering mHasSubWindow=%s\n", mHasSubWindow ? "true" : "false");
    if (!mHasSubWindow) {
        return false;
    }
    mHasSubWindow = false;

    RenderWindowMessage msg = {};
    msg.cmd = CMD_REMOVE_SUBWINDOW;
    bool result = processMessage(msg);
    D("Exiting result=%s\n", result ? "success" : "failure");
    return result;
}

void RenderWindow::setRotation(float zRot) {
    D("Entering rotation=%f\n", zRot);
    RenderWindowMessage msg = {};
    msg.cmd = CMD_SET_ROTATION;
    msg.rotation = zRot;
    (void) processMessage(msg);
    D("Exiting\n");
}

void RenderWindow::setTranslation(float px, float py) {
    D("Entering translation=%f,%f\n", px, py);
    RenderWindowMessage msg = {};
    msg.cmd = CMD_SET_TRANSLATION;
    msg.trans.px = px;
    msg.trans.py = py;
    (void) processMessage(msg);
    D("Exiting\n");
}

void RenderWindow::repaint() {
    D("Entering\n");
    RenderWindowMessage msg = {};
    msg.cmd = CMD_REPAINT;
    (void) processMessage(msg);
    D("Exiting\n");
}

bool RenderWindow::processMessage(const RenderWindowMessage& msg) {
    if (mChannel) {
        return mChannel->sendMessageAndGetResult(msg);
    } else {
        return msg.process();
    }
}
