/*
 * Copyright (C) 2009 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 "rsContext.h"
#include "rsThreadIO.h"
#include "rsgApiStructs.h"

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <fcntl.h>
#include <poll.h>


using namespace android;
using namespace android::renderscript;

ThreadIO::ThreadIO() {
    mRunning = true;
    mMaxInlineSize = 1024;
}

ThreadIO::~ThreadIO() {
}

void ThreadIO::init() {
    mToClient.init();
    mToCore.init();
}

void ThreadIO::shutdown() {
    mRunning = false;
    mToCore.shutdown();
}

void * ThreadIO::coreHeader(uint32_t cmdID, size_t dataLen) {
    //ALOGE("coreHeader %i %i", cmdID, dataLen);
    CoreCmdHeader *hdr = (CoreCmdHeader *)&mSendBuffer[0];
    hdr->bytes = dataLen;
    hdr->cmdID = cmdID;
    mSendLen = dataLen + sizeof(CoreCmdHeader);
    //mToCoreSocket.writeAsync(&hdr, sizeof(hdr));
    //ALOGE("coreHeader ret ");
    return &mSendBuffer[sizeof(CoreCmdHeader)];
}

void ThreadIO::coreCommit() {
    mToCore.writeAsync(&mSendBuffer, mSendLen);
}

void ThreadIO::clientShutdown() {
    mToClient.shutdown();
}

void ThreadIO::coreWrite(const void *data, size_t len) {
    //ALOGV("core write %p %i", data, (int)len);
    mToCore.writeAsync(data, len, true);
}

void ThreadIO::coreRead(void *data, size_t len) {
    //ALOGV("core read %p %i", data, (int)len);
    mToCore.read(data, len);
}

void ThreadIO::coreSetReturn(const void *data, size_t dataLen) {
    uint32_t buf;
    if (data == nullptr) {
        data = &buf;
        dataLen = sizeof(buf);
    }

    mToCore.readReturn(data, dataLen);
}

void ThreadIO::coreGetReturn(void *data, size_t dataLen) {
    uint32_t buf;
    if (data == nullptr) {
        data = &buf;
        dataLen = sizeof(buf);
    }

    mToCore.writeWaitReturn(data, dataLen);
}

void ThreadIO::setTimeoutCallback(void (*cb)(void *), void *dat, uint64_t timeout) {
    //mToCore.setTimeoutCallback(cb, dat, timeout);
}

bool ThreadIO::playCoreCommands(Context *con, int waitFd) {
    bool ret = false;

    uint8_t buf[2 * 1024];
    const CoreCmdHeader *cmd = (const CoreCmdHeader *)&buf[0];
    const void * data = (const void *)&buf[sizeof(CoreCmdHeader)];

    struct pollfd p[2];
    p[0].fd = mToCore.getReadFd();
    p[0].events = POLLIN;
    p[0].revents = 0;
    p[1].fd = waitFd;
    p[1].events = POLLIN;
    p[1].revents = 0;
    int pollCount = 1;
    if (waitFd >= 0) {
        pollCount = 2;
    }

    if (con->props.mLogTimes) {
        con->timerSet(Context::RS_TIMER_IDLE);
    }

    int waitTime = -1;
    while (mRunning) {
        int pr = poll(p, pollCount, waitTime);
        if (pr <= 0) {
            break;
        }

        if (p[0].revents) {
            size_t r = 0;
            r = mToCore.read(&buf[0], sizeof(CoreCmdHeader));
            mToCore.read(&buf[sizeof(CoreCmdHeader)], cmd->bytes);
            if (r != sizeof(CoreCmdHeader)) {
              // exception or timeout occurred.
              break;
            }

            ret = true;
            if (con->props.mLogTimes) {
                con->timerSet(Context::RS_TIMER_INTERNAL);
            }
            //ALOGV("playCoreCommands 3 %i %i", cmd->cmdID, cmd->bytes);

            if (cmd->cmdID >= (sizeof(gPlaybackFuncs) / sizeof(void *))) {
                rsAssert(cmd->cmdID < (sizeof(gPlaybackFuncs) / sizeof(void *)));
                ALOGE("playCoreCommands error con %p, cmd %i", con, cmd->cmdID);
            }

            gPlaybackFuncs[cmd->cmdID](con, data, cmd->bytes);

            if (con->props.mLogTimes) {
                con->timerSet(Context::RS_TIMER_IDLE);
            }

            if (waitFd < 0) {
                // If we don't have a secondary wait object we should stop blocking now
                // that at least one command has been processed.
                waitTime = 0;
            }
        }

        if (p[1].revents && !p[0].revents) {
            // We want to finish processing fifo events before processing the vsync.
            // Otherwise we can end up falling behind and having tremendous lag.
            break;
        }
    }
    return ret;
}

RsMessageToClientType ThreadIO::getClientHeader(size_t *receiveLen, uint32_t *usrID) {
    //ALOGE("getClientHeader");
    mToClient.read(&mLastClientHeader, sizeof(mLastClientHeader));

    receiveLen[0] = mLastClientHeader.bytes;
    usrID[0] = mLastClientHeader.userID;
    //ALOGE("getClientHeader %i %i %i", mLastClientHeader.cmdID, usrID[0], receiveLen[0]);
    return (RsMessageToClientType)mLastClientHeader.cmdID;
}

RsMessageToClientType ThreadIO::getClientPayload(void *data, size_t *receiveLen,
                                uint32_t *usrID, size_t bufferLen) {
    //ALOGE("getClientPayload");
    receiveLen[0] = mLastClientHeader.bytes;
    usrID[0] = mLastClientHeader.userID;
    if (bufferLen < mLastClientHeader.bytes) {
        return RS_MESSAGE_TO_CLIENT_RESIZE;
    }
    if (receiveLen[0]) {
        mToClient.read(data, receiveLen[0]);
    }
    //ALOGE("getClientPayload x");
    return (RsMessageToClientType)mLastClientHeader.cmdID;
}

bool ThreadIO::sendToClient(RsMessageToClientType cmdID, uint32_t usrID, const void *data,
                            size_t dataLen, bool waitForSpace) {

    //ALOGE("sendToClient %i %i %i", cmdID, usrID, (int)dataLen);
    ClientCmdHeader hdr;
    hdr.bytes = (uint32_t)dataLen;
    hdr.cmdID = cmdID;
    hdr.userID = usrID;

    mToClient.writeAsync(&hdr, sizeof(hdr));
    if (dataLen) {
        mToClient.writeAsync(data, dataLen);
    }

    //ALOGE("sendToClient x");
    return true;
}

