/*
 * 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"

using namespace android;
using namespace android::renderscript;

ThreadIO::ThreadIO() {
    mToCore.init(16 * 1024);
}

ThreadIO::~ThreadIO() {
}

void ThreadIO::init(bool useSocket) {
    mUsingSocket = useSocket;

    if (mUsingSocket) {
        mToClientSocket.init();
        mToCoreSocket.init();
    } else {
        mToClient.init(1024);
    }
}

void ThreadIO::shutdown() {
    //LOGE("shutdown 1");
    mToCore.shutdown();
    //LOGE("shutdown 2");
}

void ThreadIO::coreFlush() {
    //LOGE("coreFlush 1");
    if (mUsingSocket) {
    } else {
        mToCore.flush();
    }
    //LOGE("coreFlush 2");
}

void * ThreadIO::coreHeader(uint32_t cmdID, size_t dataLen) {
    //LOGE("coreHeader %i %i", cmdID, dataLen);
    if (mUsingSocket) {
        CoreCmdHeader hdr;
        hdr.bytes = dataLen;
        hdr.cmdID = cmdID;
        mToCoreSocket.writeAsync(&hdr, sizeof(hdr));
    } else {
        mCoreCommandSize = dataLen;
        mCoreCommandID = cmdID;
        mCoreDataPtr = (uint8_t *)mToCore.reserve(dataLen);
        mCoreDataBasePtr = mCoreDataPtr;
    }
    //LOGE("coreHeader ret %p", mCoreDataPtr);
    return mCoreDataPtr;
}

void ThreadIO::coreData(const void *data, size_t dataLen) {
    //LOGE("coreData %p %i", data, dataLen);
    mToCoreSocket.writeAsync(data, dataLen);
    //LOGE("coreData ret %p", mCoreDataPtr);
}

void ThreadIO::coreCommit() {
    //LOGE("coreCommit %p %p %i", mCoreDataPtr, mCoreDataBasePtr, mCoreCommandSize);
    if (mUsingSocket) {
    } else {
        rsAssert((size_t)(mCoreDataPtr - mCoreDataBasePtr) <= mCoreCommandSize);
        mToCore.commit(mCoreCommandID, mCoreCommandSize);
    }
    //LOGE("coreCommit ret");
}

void ThreadIO::coreCommitSync() {
    //LOGE("coreCommitSync %p %p %i", mCoreDataPtr, mCoreDataBasePtr, mCoreCommandSize);
    if (mUsingSocket) {
    } else {
        rsAssert((size_t)(mCoreDataPtr - mCoreDataBasePtr) <= mCoreCommandSize);
        mToCore.commitSync(mCoreCommandID, mCoreCommandSize);
    }
    //LOGE("coreCommitSync ret");
}

void ThreadIO::clientShutdown() {
    //LOGE("coreShutdown 1");
    mToClient.shutdown();
    //LOGE("coreShutdown 2");
}

void ThreadIO::coreSetReturn(const void *data, size_t dataLen) {
    rsAssert(dataLen <= sizeof(mToCoreRet));
    memcpy(&mToCoreRet, data, dataLen);
}

void ThreadIO::coreGetReturn(void *data, size_t dataLen) {
    memcpy(data, &mToCoreRet, dataLen);
}


bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand) {
    bool ret = false;
    while (!mToCore.isEmpty() || waitForCommand) {
        uint32_t cmdID = 0;
        uint32_t cmdSize = 0;
        ret = true;
        if (con->props.mLogTimes) {
            con->timerSet(Context::RS_TIMER_IDLE);
        }
        const void * data = mToCore.get(&cmdID, &cmdSize);
        if (!cmdSize) {
            // exception occured, probably shutdown.
            return false;
        }
        if (con->props.mLogTimes) {
            con->timerSet(Context::RS_TIMER_INTERNAL);
        }
        waitForCommand = false;
        //LOGV("playCoreCommands 3 %i %i", cmdID, cmdSize);

        if (cmdID >= (sizeof(gPlaybackFuncs) / sizeof(void *))) {
            rsAssert(cmdID < (sizeof(gPlaybackFuncs) / sizeof(void *)));
            LOGE("playCoreCommands error con %p, cmd %i", con, cmdID);
            mToCore.printDebugData();
        }
        gPlaybackFuncs[cmdID](con, data, cmdSize << 2);
        mToCore.next();
    }
    return ret;
}

RsMessageToClientType ThreadIO::getClientHeader(size_t *receiveLen, uint32_t *usrID) {
    if (mUsingSocket) {
        mToClientSocket.read(&mLastClientHeader, sizeof(mLastClientHeader));
    } else {
        size_t bytesData = 0;
        const uint32_t *d = (const uint32_t *)mToClient.get(&mLastClientHeader.cmdID, (uint32_t*)&bytesData);
        if (bytesData >= sizeof(uint32_t)) {
            mLastClientHeader.userID = d[0];
            mLastClientHeader.bytes = bytesData - sizeof(uint32_t);
        } else {
            mLastClientHeader.userID = 0;
            mLastClientHeader.bytes = 0;
        }
    }
    receiveLen[0] = mLastClientHeader.bytes;
    usrID[0] = mLastClientHeader.userID;
    return (RsMessageToClientType)mLastClientHeader.cmdID;
}

RsMessageToClientType ThreadIO::getClientPayload(void *data, size_t *receiveLen,
                                uint32_t *usrID, size_t bufferLen) {
    receiveLen[0] = mLastClientHeader.bytes;
    usrID[0] = mLastClientHeader.userID;
    if (bufferLen < mLastClientHeader.bytes) {
        return RS_MESSAGE_TO_CLIENT_RESIZE;
    }
    if (mUsingSocket) {
        if (receiveLen[0]) {
            mToClientSocket.read(data, receiveLen[0]);
        }
        return (RsMessageToClientType)mLastClientHeader.cmdID;
    } else {
        uint32_t bytesData = 0;
        uint32_t commandID = 0;
        const uint32_t *d = (const uint32_t *)mToClient.get(&commandID, &bytesData);
        //LOGE("getMessageToClient 3    %i  %i", commandID, bytesData);
        //LOGE("getMessageToClient  %i %i", commandID, *subID);
        if (bufferLen >= receiveLen[0]) {
            memcpy(data, d+1, receiveLen[0]);
            mToClient.next();
            return (RsMessageToClientType)commandID;
        }
    }
    return RS_MESSAGE_TO_CLIENT_RESIZE;
}

bool ThreadIO::sendToClient(RsMessageToClientType cmdID, uint32_t usrID, const void *data,
                            size_t dataLen, bool waitForSpace) {
    ClientCmdHeader hdr;
    hdr.bytes = dataLen;
    hdr.cmdID = cmdID;
    hdr.userID = usrID;
    if (mUsingSocket) {
        mToClientSocket.writeAsync(&hdr, sizeof(hdr));
        if (dataLen) {
            mToClientSocket.writeAsync(data, dataLen);
        }
        return true;
    } else {
        if (!waitForSpace) {
            if (!mToClient.makeSpaceNonBlocking(dataLen + sizeof(hdr))) {
                // Not enough room, and not waiting.
                return false;
            }
        }

        //LOGE("sendMessageToClient 2");
        uint32_t *p = (uint32_t *)mToClient.reserve(dataLen + sizeof(usrID));
        p[0] = usrID;
        if (dataLen > 0) {
            memcpy(p+1, data, dataLen);
        }
        mToClient.commit(cmdID, dataLen + sizeof(usrID));
        //LOGE("sendMessageToClient 3");
        return true;
    }
    return false;
}

