/*
 ** Copyright 2011, 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 <sys/ioctl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

#include "header.h"

namespace android
{

int serverSock = -1, clientSock = -1;
FILE * file = NULL;
unsigned int MAX_FILE_SIZE = 0;
int timeMode = SYSTEM_TIME_THREAD;

static void Die(const char * msg)
{
    LOGD("\n*\n*\n* GLESv2_dbg: Die: %s \n*\n*", msg);
    StopDebugServer();
    exit(1);
}

void StartDebugServer(const unsigned short port, const bool forceUseFile,
                      const unsigned int maxFileSize, const char * const filePath)
{
    MAX_FILE_SIZE = maxFileSize;

    LOGD("GLESv2_dbg: StartDebugServer");
    if (serverSock >= 0 || file)
        return;

    LOGD("GLESv2_dbg: StartDebugServer create socket");
    struct sockaddr_in server = {}, client = {};

    /* Create the TCP socket */
    if (forceUseFile || (serverSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        file = fopen(filePath, "wb");
        if (!file)
            Die("Failed to create socket and file");
        else
            return;
    }
    /* Construct the server sockaddr_in structure */
    server.sin_family = AF_INET;                  /* Internet/IP */
    server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);   /* Incoming addr */
    server.sin_port = htons(port);       /* server port */

    /* Bind the server socket */
    socklen_t sizeofSockaddr_in = sizeof(sockaddr_in);
    if (bind(serverSock, (struct sockaddr *) &server,
             sizeof(server)) < 0) {
        Die("Failed to bind the server socket");
    }
    /* Listen on the server socket */
    if (listen(serverSock, 1) < 0) {
        Die("Failed to listen on server socket");
    }

    LOGD("server started on %d \n", server.sin_port);


    /* Wait for client connection */
    if ((clientSock =
                accept(serverSock, (struct sockaddr *) &client,
                       &sizeofSockaddr_in)) < 0) {
        Die("Failed to accept client connection");
    }

    LOGD("Client connected: %s\n", inet_ntoa(client.sin_addr));
//    fcntl(clientSock, F_SETFL, O_NONBLOCK);
}

void StopDebugServer()
{
    LOGD("GLESv2_dbg: StopDebugServer");
    if (clientSock > 0) {
        close(clientSock);
        clientSock = -1;
    }
    if (serverSock > 0) {
        close(serverSock);
        serverSock = -1;
    }
    if (file) {
        fclose(file);
        file = NULL;
    }
}

void Receive(glesv2debugger::Message & cmd)
{
    if (clientSock < 0)
        return;
    unsigned len = 0;
    int received = recv(clientSock, &len, 4, MSG_WAITALL);
    if (received < 0)
        Die("Failed to receive response length");
    else if (4 != received) {
        LOGD("received %dB: %.8X", received, len);
        Die("Received length mismatch, expected 4");
    }
    static void * buffer = NULL;
    static unsigned bufferSize = 0;
    if (bufferSize < len) {
        buffer = realloc(buffer, len);
        assert(buffer);
        bufferSize = len;
    }
    received = recv(clientSock, buffer, len, MSG_WAITALL);
    if (received < 0)
        Die("Failed to receive response");
    else if (len != received)
        Die("Received length mismatch");
    cmd.Clear();
    cmd.ParseFromArray(buffer, len);
}

bool TryReceive(glesv2debugger::Message & cmd)
{
    if (clientSock < 0)
        return false;
    fd_set readSet;
    FD_ZERO(&readSet);
    FD_SET(clientSock, &readSet);
    timeval timeout;
    timeout.tv_sec = timeout.tv_usec = 0;

    int rc = select(clientSock + 1, &readSet, NULL, NULL, &timeout);
    if (rc < 0)
        Die("failed to select clientSock");

    bool received = false;
    if (FD_ISSET(clientSock, &readSet)) {
        LOGD("TryReceive: avaiable for read");
        Receive(cmd);
        return true;
    }
    return false;
}

float Send(const glesv2debugger::Message & msg, glesv2debugger::Message & cmd)
{
    // TODO: use per DbgContext send/receive buffer and async socket
    //  instead of mutex and blocking io; watch out for large messages
    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    struct Autolock {
        Autolock() {
            pthread_mutex_lock(&mutex);
        }
        ~Autolock() {
            pthread_mutex_unlock(&mutex);
        }
    } autolock;

    if (msg.function() != glesv2debugger::Message_Function_ACK)
        assert(msg.has_context_id() && msg.context_id() != 0);
    static std::string str;
    msg.SerializeToString(&str);
    const uint32_t len = str.length();
    if (clientSock < 0) {
        if (file) {
            fwrite(&len, sizeof(len), 1, file);
            fwrite(str.data(), len, 1, file);
            if (ftell(file) >= MAX_FILE_SIZE) {
                fclose(file);
                Die("MAX_FILE_SIZE reached");
            }
        }
        return 0;
    }
    int sent = -1;
    sent = send(clientSock, &len, sizeof(len), 0);
    if (sent != sizeof(len)) {
        LOGD("actual sent=%d expected=%d clientSock=%d", sent, sizeof(len), clientSock);
        Die("Failed to send message length");
    }
    nsecs_t c0 = systemTime(timeMode);
    sent = send(clientSock, str.data(), str.length(), 0);
    float t = (float)ns2ms(systemTime(timeMode) - c0);
    if (sent != str.length()) {
        LOGD("actual sent=%d expected=%d clientSock=%d", sent, str.length(), clientSock);
        Die("Failed to send message");
    }
    // TODO: factor Receive & TryReceive out and into MessageLoop, or add control argument.
    // mean while, if server is sending a SETPROP then don't try to receive,
    //  because server will not be processing received command
    if (msg.function() == msg.SETPROP)
        return t;
    // try to receive commands even though not expecting response,
    //  since client can send SETPROP and other commands anytime
    if (!msg.expect_response()) {
        if (TryReceive(cmd)) {
            if (glesv2debugger::Message_Function_SETPROP == cmd.function())
                LOGD("Send: TryReceived SETPROP");
            else
                LOGD("Send: TryReceived %u", cmd.function());
        }
    } else
        Receive(cmd);
    return t;
}

void SetProp(DbgContext * const dbg, const glesv2debugger::Message & cmd)
{
    switch (cmd.prop()) {
    case glesv2debugger::Message_Prop_CaptureDraw:
        LOGD("SetProp Message_Prop_CaptureDraw %d", cmd.arg0());
        dbg->captureDraw = cmd.arg0();
        break;
    case glesv2debugger::Message_Prop_TimeMode:
        LOGD("SetProp Message_Prop_TimeMode %d", cmd.arg0());
        timeMode = cmd.arg0();
        break;
    case glesv2debugger::Message_Prop_ExpectResponse:
        LOGD("SetProp Message_Prop_ExpectResponse %d=%d", cmd.arg0(), cmd.arg1());
        dbg->expectResponse.Bit((glesv2debugger::Message_Function)cmd.arg0(), cmd.arg1());
        break;
    case glesv2debugger::Message_Prop_CaptureSwap:
        LOGD("SetProp CaptureSwap %d", cmd.arg0());
        dbg->captureSwap = cmd.arg0();
        break;
    default:
        assert(0);
    }
}

int * MessageLoop(FunctionCall & functionCall, glesv2debugger::Message & msg,
                  const glesv2debugger::Message_Function function)
{
    DbgContext * const dbg = getDbgContextThreadSpecific();
    const int * ret = 0;
    glesv2debugger::Message cmd;
    msg.set_context_id(reinterpret_cast<int>(dbg));
    msg.set_type(glesv2debugger::Message_Type_BeforeCall);
    bool expectResponse = dbg->expectResponse.Bit(function);
    msg.set_expect_response(expectResponse);
    msg.set_function(function);

    // when not exectResponse, set cmd to CONTINUE then SKIP
    // cmd will be overwritten by received command
    cmd.set_function(glesv2debugger::Message_Function_CONTINUE);
    cmd.set_expect_response(expectResponse);
    glesv2debugger::Message_Function oldCmd = cmd.function();
    Send(msg, cmd);
    expectResponse = cmd.expect_response();
    while (true) {
        msg.Clear();
        nsecs_t c0 = systemTime(timeMode);
        switch (cmd.function()) {
        case glesv2debugger::Message_Function_CONTINUE:
            ret = functionCall(&dbg->hooks->gl, msg);
            while (GLenum error = dbg->hooks->gl.glGetError())
                LOGD("Function=%u glGetError() = 0x%.4X", function, error);
            if (!msg.has_time()) // some has output data copy, so time inside call
                msg.set_time((systemTime(timeMode) - c0) * 1e-6f);
            msg.set_context_id(reinterpret_cast<int>(dbg));
            msg.set_function(function);
            msg.set_type(glesv2debugger::Message_Type_AfterCall);
            msg.set_expect_response(expectResponse);
            if (!expectResponse) {
                cmd.set_function(glesv2debugger::Message_Function_SKIP);
                cmd.set_expect_response(false);
            }
            oldCmd = cmd.function();
            Send(msg, cmd);
            expectResponse = cmd.expect_response();
            break;
        case glesv2debugger::Message_Function_SKIP:
            return const_cast<int *>(ret);
        case glesv2debugger::Message_Function_SETPROP:
            SetProp(dbg, cmd);
            expectResponse = cmd.expect_response();
            if (!expectResponse) // SETPROP is "out of band"
                cmd.set_function(oldCmd);
            else
                Receive(cmd);
            break;
        default:
            ret = GenerateCall(dbg, cmd, msg, ret);
            msg.set_expect_response(expectResponse);
            if (!expectResponse) {
                cmd.set_function(cmd.SKIP);
                cmd.set_expect_response(expectResponse);
            }
            oldCmd = cmd.function();
            Send(msg, cmd);
            expectResponse = cmd.expect_response();
            break;
        }
    }
    return 0;
}
}; // namespace android {
