/**
 * 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) {
            LOGE("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) {
            LOGE("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) {
            LOGE("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) {
            LOGE("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) {
                LOGE("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) {
            LOGE("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
        LOGE("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) {
        LOGE("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) {
        LOGE("mock_ril control server could not start");
    } else {
        DBG("mock_ril control server started");
    }
#endif
}
