/**
 * Copyright (C) 2010 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 <alloca.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <sys/endian.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

#include <cutils/sockets.h>

#include "logging.h"
#include "node_buffer.h"
#include "status.h"
#include "util.h"
#include "worker.h"

#include "hardware/ril/mock-ril/src/proto/msgheader.pb.h"

#include "hardware/ril/mock-ril/src/proto/ctrl.pb.h"
#include "ctrl_server.h"

//#define CONTROL_SERVER_DEBUG
#ifdef  CONTROL_SERVER_DEBUG

#define DBG(...) ALOGD(__VA_ARGS__)

#else

#define DBG(...)

#endif

#define MOCK_RIL_CONTROL_SERVER_STOPPING_SOCKET 54311
#define MOCK_RIL_CONTROL_SERVER_SOCKET 54312

using communication::MsgHeader;

class CtrlServerThread;
static CtrlServerThread *g_ctrl_server;

class CtrlServerThread : public WorkerThread {
  private:
    #define SOCKET_NAME_MOCK_RIL_CST_STOPPER "mock-ril-cst-stopper"
    v8::Handle<v8::Context> context_;
    int server_accept_socket_;
    int server_to_client_socket_;
    int stop_server_fd_;
    int stop_client_fd_;
    int stopper_fd_;
    fd_set rd_fds_;
    fd_set wr_fds_;
    bool done_;

    Buffer *ObtainBuffer(int length) {
        Buffer *b = Buffer::New(length);
        return b;
    }

    int WriteAll(int s, void *data, int length) {
        int ret_value;
        uint8_t *bytes = (uint8_t *)data;
        int count = length;

        while (length > 0) {
            ret_value = send(s, bytes, length, 0);
            if (ret_value < 0) {
                return STATUS_ERR;
            }
            if (ret_value == 0) {
                return STATUS_CLIENT_CLOSED_CONNECTION;
            }
            bytes += ret_value;
            length -= ret_value;
        }

        return STATUS_OK;
    }

    int ReadAll(int s, void *data, int length) {
        int ret_value;
        uint8_t *bytes = (uint8_t *)data;
        int count = length;

        while (length != 0) {
            ret_value = recv(s, bytes, length, 0);
            if (ret_value < 0) {
                return STATUS_ERR;
            }
            if (ret_value == 0) {
                return STATUS_CLIENT_CLOSED_CONNECTION;
            }
            bytes += ret_value;
            length -= ret_value;
        }

        return STATUS_OK;
    }

    int ReadMessage(MsgHeader *mh, Buffer **pBuffer) {
        int status;
        int32_t len_msg_header;

        // Reader header length
        status = ReadAll(server_to_client_socket_, &len_msg_header, sizeof(len_msg_header));
        len_msg_header = letoh32(len_msg_header);
        DBG("rm: read len_msg_header=%d  status=%d", len_msg_header, status);
        if (status != STATUS_OK) return status;

        // Read header into an array allocated on the stack and unmarshall
        uint8_t *msg_header_raw = (uint8_t *)alloca(len_msg_header);
        status = ReadAll(server_to_client_socket_, msg_header_raw, len_msg_header);
        DBG("rm: read msg_header_raw=%p  status=%d", msg_header_raw, status);
        if (status != STATUS_OK) return status;
        mh->ParseFromArray(msg_header_raw, len_msg_header);

        // Read auxillary data
        Buffer *buffer;
        if (mh->length_data() > 0) {
            buffer = ObtainBuffer(mh->length_data());
            status = ReadAll(server_to_client_socket_, buffer->data(), buffer->length());
            DBG("rm: read protobuf status=%d", status);
            if (status != STATUS_OK) return status;
        } else {
            DBG("rm: NO protobuf");
            buffer = NULL;
        }

        *pBuffer = buffer;
        return STATUS_OK;
    }

  public:
    int WriteMessage(MsgHeader *mh, Buffer *buffer) {
        int status;
        uint32_t i;
        uint64_t l;

        // Set length of data
        if (buffer == NULL) {
            mh->set_length_data(0);
        } else {
            mh->set_length_data(buffer->length());
        }

        // Serialize header
        uint32_t len_msg_header = mh->ByteSize();
        uint8_t *msg_header_raw = (uint8_t *)alloca(len_msg_header);
        mh->SerializeToArray(msg_header_raw, len_msg_header);

        // Write length in little endian followed by the header
        i = htole32(len_msg_header);
        status = WriteAll(server_to_client_socket_, &i, 4);
        DBG("wm: write len_msg_header=%d status=%d", len_msg_header, status);
        if (status != 0) return status;
        status = WriteAll(server_to_client_socket_, msg_header_raw, len_msg_header);
        DBG("wm: write msg_header_raw=%p  status=%d", msg_header_raw, status);
        if (status != 0) return status;

        // Write data
        if (mh->length_data() > 0) {
            status = WriteAll(server_to_client_socket_, buffer->data(), buffer->length());
            DBG("wm: protobuf data=%p len=%d status=%d",
                    buffer->data(), buffer->length(), status);
            if (status != 0) return status;
        }

        return STATUS_OK;
    }

    CtrlServerThread(v8::Handle<v8::Context> context) :
            context_(context),
            server_accept_socket_(-1),
            server_to_client_socket_(-1),
            done_(false) {
    }

    virtual int Run() {
        DBG("CtrlServerThread::Run E");

        // Create a server socket.
        server_accept_socket_ = socket_inaddr_any_server(
            MOCK_RIL_CONTROL_SERVER_SOCKET, SOCK_STREAM);
        if (server_accept_socket_ < 0) {
            ALOGE("CtrlServerThread::Run error creating server_accept_socket_ '%s'",
                    strerror(errno));
            return STATUS_ERR;
        }

        // Create a server socket that will be used for stopping
        stop_server_fd_ = socket_loopback_server(
                MOCK_RIL_CONTROL_SERVER_STOPPING_SOCKET, SOCK_STREAM);
        if (stop_server_fd_ < 0) {
            ALOGE("CtrlServerThread::Run error creating stop_server_fd_ '%s'",
                    strerror(errno));
            return STATUS_ERR;
        }

        // Create a client socket that will be used for sending a stop
        stop_client_fd_ = socket_loopback_client(
                MOCK_RIL_CONTROL_SERVER_STOPPING_SOCKET, SOCK_STREAM);
        if (stop_client_fd_ < 0) {
            ALOGE("CtrlServerThread::Run error creating stop_client_fd_ '%s'",
                    strerror(errno));
            return STATUS_ERR;
        }

        // Accept the connection of the stop_client_fd_
        stopper_fd_ = accept(stop_server_fd_, NULL, NULL);
        if (stopper_fd_ < 0) {
            ALOGE("CtrlServerThread::Run error accepting stop_client_fd '%s'",
                    strerror(errno));
            return STATUS_ERR;
        }

        // Run the new thread
        int ret_value = WorkerThread::Run(NULL);
        DBG("CtrlServerThread::Run X");
        return ret_value;
    }

    virtual void Stop() {
        DBG("CtrlServerThread::Stop E");
        if (BeginStopping()) {
            done_ = true;
            int rv = send(stop_client_fd_, &done_, sizeof(done_), 0);
            if (rv <= 0) {
                ALOGE("CtrlServerThread::Stop could not send stop"
                            "WE WILL PROBABLY HANG");
            }
            WaitUntilStopped();
        }
        DBG("CtrlServerThread::Stop X");
    }

    virtual bool isRunning() {
        bool rv = done_ || WorkerThread::isRunning();
        return rv;
    }

    int WaitOnSocketOrStopping(fd_set *rfds, int s) {
        DBG("WaitOnSocketOrStopping E s=%d stopper_fd_=%d", s, stopper_fd_);
        FD_ZERO(rfds);
        FD_SET(s, rfds);
        FD_SET(stopper_fd_, rfds);
        int fd_number = s > stopper_fd_ ? s + 1 : stopper_fd_ + 1;
        v8::Unlocker unlocker;
        int rv = select(fd_number, rfds, NULL, NULL, NULL);
        v8::Locker locker;
        DBG("WaitOnSocketOrStopping X rv=%d s=%d stopper_fd_=%d", rv, s, stopper_fd_);
        return rv;
    }

    int sendToCtrlServer(MsgHeader *mh, Buffer *buffer) {
        DBG("sendToCtrlServer E: cmd=%d token=%lld", mh->cmd(), mh->token());

        int status = STATUS_OK;
        v8::HandleScope handle_scope;
        v8::TryCatch try_catch;
        try_catch.SetVerbose(true);

        // Get the onRilRequest Function
        v8::Handle<v8::String> name = v8::String::New("onCtrlServerCmd");
        v8::Handle<v8::Value> onCtrlServerCmdFunctionValue =
                context_->Global()->Get(name);
        v8::Handle<v8::Function> onCtrlServerCmdFunction =
                v8::Handle<v8::Function>::Cast(onCtrlServerCmdFunctionValue);

        // Create the CmdValue and TokenValue
        v8::Handle<v8::Value> v8CmdValue = v8::Number::New(mh->cmd());
        v8::Handle<v8::Value> v8TokenValue = v8::Number::New(mh->token());

        // Invoke onRilRequest
        const int argc = 3;
        v8::Handle<v8::Value> buf;
        if (mh->length_data() == 0) {
            buf = v8::Undefined();
        } else {
            buf = buffer->handle_;
        }
        v8::Handle<v8::Value> argv[argc] = {
                v8CmdValue, v8TokenValue, buf };
        v8::Handle<v8::Value> result =
            onCtrlServerCmdFunction->Call(context_->Global(), argc, argv);
        if (try_catch.HasCaught()) {
            ReportException(&try_catch);
            status = STATUS_ERR;
        } else {
            v8::String::Utf8Value result_string(result);
            DBG("sendToCtrlServer result=%s", ToCString(result_string));
            status = STATUS_OK;
        }

        if (status != STATUS_OK) {
            ALOGE("sendToCtrlServer Error: status=%d", status);
            // An error report complete now
            mh->set_length_data(0);
            mh->set_status(ril_proto::CTRL_STATUS_ERR);
            g_ctrl_server->WriteMessage(mh, NULL);
        }

        DBG("sendToCtrlServer X: status=%d", status);
        return status;
    }

    virtual void * Worker(void *param) {
        DBG("CtrlServerThread::Worker E param=%p stopper_fd_=%d",
                param, stopper_fd_);

        v8::Locker locker;
        v8::HandleScope handle_scope;
        v8::Context::Scope context_scope(context_);

        while (isRunning()) {
            int ret_value;

            // Wait on either server_accept_socket_ or stopping
            DBG("CtrlServerThread::Worker wait on server for a client");
            WaitOnSocketOrStopping(&rd_fds_, server_accept_socket_);
            if (isRunning() != true) {
                break;
            }

            if (FD_ISSET(server_accept_socket_, &rd_fds_)) {
                server_to_client_socket_ = accept(server_accept_socket_, NULL, NULL);
                DBG("CtrlServerThread::Worker accepted server_to_client_socket_=%d isRunning()=%d",
                        server_to_client_socket_, isRunning());

                int status;
                Buffer *buffer;
                MsgHeader mh;
                while ((server_to_client_socket_ > 0) && isRunning()) {
                    DBG("CtrlServerThread::Worker wait on client for message");
                    WaitOnSocketOrStopping(&rd_fds_, server_to_client_socket_);
                    if (isRunning() != true) {
                        break;
                    }

                    status = ReadMessage(&mh, &buffer);
                    if (status != STATUS_OK) break;

                    if (mh.cmd() == ril_proto::CTRL_CMD_ECHO) {
                        ALOGD("CtrlServerThread::Worker echo");
                        status = WriteMessage(&mh, buffer);
                        if (status != STATUS_OK) break;
                    } else {
                        DBG("CtrlServerThread::Worker sendToCtrlServer");
                        status = sendToCtrlServer(&mh, buffer);
                        if (status != STATUS_OK) break;
                    }
                }
                close(server_to_client_socket_);
                server_to_client_socket_ = -1;
            }
        }
        close(stop_server_fd_);
        stop_server_fd_ = -1;

        close(stop_client_fd_);
        stop_client_fd_ = -1;

        close(stopper_fd_);
        stopper_fd_ = -1;

        close(server_accept_socket_);
        server_accept_socket_ = -1;

        DBG("CtrlServerThread::Worker X param=%p", param);
        return NULL;
    }
};

/**
 * Send a control request complete response.
 */
v8::Handle<v8::Value> SendCtrlRequestComplete(const v8::Arguments& args) {
    DBG("SendCtrlRequestComplete E:");
    v8::HandleScope handle_scope;
    v8::Handle<v8::Value> retValue;

    void *data;
    size_t datalen;

    Buffer* buffer;
    MsgHeader mh;

    /**
     * Get the arguments. There should be at least 3, reqNum,
     * ril error code and token. Optionally a Buffer containing
     * the protobuf representation of the data to return.
     */
    if (args.Length() < 3) {
        // Expecting a reqNum, ERROR and token
        ALOGE("SendCtrlRequestComplete X %d parameters"
             " expecting at least 3: status, reqNum, and token",
                args.Length());
        return v8::Undefined();
    }
    v8::Handle<v8::Value> v8CtrlStatus(args[0]->ToObject());
    mh.set_status(ril_proto::CtrlStatus(v8CtrlStatus->NumberValue()));
    DBG("SendCtrlRequestComplete: status=%d", mh.status());

    v8::Handle<v8::Value> v8ReqNum(args[1]->ToObject());
    mh.set_cmd(int(v8ReqNum->NumberValue()));
    DBG("SendCtrlRequestComplete: cmd=%d", mh.cmd());

    v8::Handle<v8::Value> v8Token(args[2]->ToObject());
    mh.set_token(int64_t(v8Token->NumberValue()));
    DBG("SendCtrlRequestComplete: token=%lld", mh.token());

    if (args.Length() >= 4) {
        buffer = ObjectWrap::Unwrap<Buffer>(args[3]->ToObject());
        mh.set_length_data(buffer->length());
        DBG("SendCtrlRequestComplete: mh.length_data=%d",
                mh.length_data());
    } else {
        mh.set_length_data(0);
        buffer = NULL;
        DBG("SendCtrlRequestComplete: NO PROTOBUF");
    }

    DBG("SendCtrlRequestComplete: WriteMessage");
    int status = g_ctrl_server->WriteMessage(&mh, buffer);

    DBG("SendCtrlRequestComplete E:");
    return v8::Undefined();
}

void ctrlServerInit(v8::Handle<v8::Context> context) {
    int status;

    g_ctrl_server = new CtrlServerThread(context);
    status = g_ctrl_server->Run();
    if (status != STATUS_OK) {
        ALOGE("mock_ril control server could not start");
    } else {
        ALOGD("CtrlServer started");
    }

#if 0
    ALOGD("Test CtrlServerThread stop sleeping 10 seconds...");
    v8::Unlocker unlocker;
    sleep(10);
    ALOGD("Test CtrlServerThread call Stop");
    g_ctrl_server->Stop();
    v8::Locker locker;

    // Restart
    g_ctrl_server = new CtrlServerThread(context);
    status = g_ctrl_server->Run();
    if (status != STATUS_OK) {
        ALOGE("mock_ril control server could not start");
    } else {
        DBG("mock_ril control server started");
    }
#endif
}
