/*
 * Copyright (C) 2012 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 <arpa/inet.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <utils/Looper.h>

#include "Log.h"
#include "audio/AudioProtocol.h"
#include "audio/RemoteAudio.h"


RemoteAudio::RemoteAudio(ClientSocket& socket)
    : mExitRequested(false),
      mSocket(socket),
      mDownloadHandler(new CommandHandler(*this, (int)AudioProtocol::ECmdDownload)),
      mPlaybackHandler(new CommandHandler(*this, (int)AudioProtocol::ECmdStartPlayback)),
      mRecordingHandler(new CommandHandler(*this, (int)AudioProtocol::ECmdStartRecording)),
      mDeviceInfoHandler(new CommandHandler(*this, (int)AudioProtocol::ECmdGetDeviceInfo)),
      mDownloadId(0)
{
    mCmds[AudioProtocol::ECmdDownload - AudioProtocol::ECmdStart] = new CmdDownload(socket);
    mCmds[AudioProtocol::ECmdStartPlayback - AudioProtocol::ECmdStart] =
            new CmdStartPlayback(socket);
    mCmds[AudioProtocol::ECmdStopPlayback - AudioProtocol::ECmdStart] =
            new CmdStopPlayback(socket);
    mCmds[AudioProtocol::ECmdStartRecording - AudioProtocol::ECmdStart] =
            new CmdStartRecording(socket);
    mCmds[AudioProtocol::ECmdStopRecording - AudioProtocol::ECmdStart] =
            new CmdStopRecording(socket);
    mCmds[AudioProtocol::ECmdGetDeviceInfo - AudioProtocol::ECmdStart] =
                new CmdGetDeviceInfo(socket);
}

RemoteAudio::~RemoteAudio()
{
    for (int i = 0; i < (AudioProtocol::ECmdLast - AudioProtocol::ECmdStart); i++) {
        delete mCmds[i];
    }
    //mBufferList.clear();
}

bool RemoteAudio::init(int port)
{
    mPort = port;
    if (run("RemoteAudio") != android::NO_ERROR) {
        LOGE("RemoteAudio cannot run");
        // cannot run thread
        return false;
    }

    if (!mInitWait.timedWait(CLIENT_WAIT_TIMEOUT_MSEC)) {
        return false;
    }
    return mInitResult;
}

bool RemoteAudio::threadLoop()
{
    // initial action until socket connection done by init
    mLooper = new android::Looper(false);
    if (mLooper.get() == NULL) {
        wakeClient(false);
        return false;
    }
    android::Looper::setForThread(mLooper);

    if (!mSocket.init("127.0.0.1", mPort)) {
        wakeClient(false);
        return false;
    }
    LOGD("adding fd %d to polling", mSocket.getFD());
    mLooper->addFd(mSocket.getFD(), EIdSocket, android::Looper::EVENT_INPUT, socketRxCallback, this);
    wakeClient(true);
    while(!mExitRequested) {
        mLooper->pollOnce(10000);
    }
    return false; // exit without requestExit()
}

void RemoteAudio::wakeClient(bool result)
{
    mInitResult = result;
    mInitWait.post();
}

bool RemoteAudio::handlePacket()
{
    uint32_t data[AudioProtocol::REPLY_HEADER_SIZE/sizeof(uint32_t)];
    AudioProtocol::CommandId id;
    if (!AudioProtocol::handleReplyHeader(mSocket, data, id)) {
        return false;
    }
    CommandHandler* handler = NULL;
    if (id == AudioProtocol::ECmdDownload) {
        handler = reinterpret_cast<CommandHandler*>(mDownloadHandler.get());
    } else if (id == AudioProtocol::ECmdStartPlayback) {
        handler = reinterpret_cast<CommandHandler*>(mPlaybackHandler.get());
    } else if (id == AudioProtocol::ECmdStartRecording) {
        handler = reinterpret_cast<CommandHandler*>(mRecordingHandler.get());
    } else if (id == AudioProtocol::ECmdGetDeviceInfo) {
        handler = reinterpret_cast<CommandHandler*>(mDeviceInfoHandler.get());
    }
    AudioParam* param = NULL;
    if (handler != NULL) {
        param = &(handler->getParam());
    }
    bool result = mCmds[id - AudioProtocol::ECmdStart]->handleReply(data, param);
    if (handler != NULL) {
        LOGD("handler present. Notify client");
        android::Mutex::Autolock lock(handler->mStateLock);
        if (handler->mNotifyOnReply) {
            handler->mNotifyOnReply = false;
            handler->mResult = result;
            handler->mClientWait.post();
        }
        handler->mActive = false;
    }
    return result;
}

int RemoteAudio::socketRxCallback(int fd, int events, void* data)
{
    RemoteAudio* self = reinterpret_cast<RemoteAudio*>(data);
    if (events & android::Looper::EVENT_INPUT) {
        //LOGD("socketRxCallback input");
        if (!self->handlePacket()) { //error, stop polling
            LOGE("socketRxCallback, error in packet, stopping polling");
            return 0;
        }
    }
    return 1;
}

void RemoteAudio::sendCommand(android::sp<android::MessageHandler>& command)
{
    mLooper->sendMessage(command, toCommandHandler(command)->getMessage());
}

bool RemoteAudio::waitForCompletion(android::sp<android::MessageHandler>& command, int timeInMSec)
{
    LOGV("waitForCompletion %d", timeInMSec);
    return toCommandHandler(command)->timedWait(timeInMSec);
}

bool RemoteAudio::waitForPlaybackOrRecordingCompletion(
        android::sp<android::MessageHandler>& commandHandler)
{
    CommandHandler* handler = reinterpret_cast<CommandHandler*>(commandHandler.get());
    handler->mStateLock.lock();
    if(!handler->mActive) {
        handler->mStateLock.unlock();
        return true;
    }
    int runTime = handler->getParam().mBuffer->getSize() /
            (handler->getParam().mStereo ? 4 : 2) * 1000 / handler->getParam().mSamplingF;
    handler->mNotifyOnReply = true;
    handler->mStateLock.unlock();
    return waitForCompletion(commandHandler, runTime + CLIENT_WAIT_TIMEOUT_MSEC);
}

void RemoteAudio::doStop(android::sp<android::MessageHandler>& commandHandler,
        AudioProtocol::CommandId id)
{
    CommandHandler* handler = reinterpret_cast<CommandHandler*>(commandHandler.get());
    handler->mStateLock.lock();
    if (!handler->mActive) {
        handler->mStateLock.unlock();
       return;
    }
    handler->mActive = false;
    handler->mNotifyOnReply = false;
    handler->mStateLock.unlock();
    android::sp<android::MessageHandler> command(new CommandHandler(*this, (int)id));
    sendCommand(command);
    waitForCompletion(command, CLIENT_WAIT_TIMEOUT_MSEC);
}


bool RemoteAudio::downloadData(const android::String8& name, android::sp<Buffer>& buffer, int& id)
{
    CommandHandler* handler = reinterpret_cast<CommandHandler*>(mDownloadHandler.get());
    id = mDownloadId;
    mDownloadId++;
    handler->mStateLock.lock();
    handler->getParam().mId = id;
    handler->getParam().mBuffer = buffer;
    handler->mNotifyOnReply = true;
    handler->mStateLock.unlock();
    sendCommand(mDownloadHandler);

    // assume 1Mbps ==> 1000 bits per msec ==> 125 bytes per msec
    int maxWaitTime = CLIENT_WAIT_TIMEOUT_MSEC + buffer->getSize() / 125;
    // client blocked until reply comes from DUT
    if (!waitForCompletion(mDownloadHandler, maxWaitTime)) {
        LOGE("timeout");
        return false;
    }
    mBufferList[id] = buffer;
    mIdMap[name] = id;
    return handler->mResult;
}

int RemoteAudio::getDataId(const android::String8& name)
{
    std::map<android::String8, int>::iterator it;
    it = mIdMap.find(name);
    if (it == mIdMap.end()) {
        LOGE("Buffer name %s not registered", name.string());
        return -1;
    }
    return it->second;
}

bool RemoteAudio::startPlayback(bool stereo, int samplingF, int mode, int volume,
        int id, int numberRepetition)
{
    CommandHandler* handler = reinterpret_cast<CommandHandler*>(mPlaybackHandler.get());
    handler->mStateLock.lock();
    if (handler->mActive) {
        LOGE("busy");
        handler->mStateLock.unlock();
        return false;
    }
    std::map<int, android::sp<Buffer> >::iterator it;
    it = mBufferList.find(id);
    if (it == mBufferList.end()) {
        LOGE("Buffer id %d not registered", id);
        return false;
    }
    LOGD("RemoteAudio::startPlayback stereo %d mode %d", stereo, mode);
    handler->mActive = true;
    handler->getParam().mStereo = stereo;
    handler->getParam().mSamplingF = samplingF;
    handler->getParam().mMode = mode;
    handler->getParam().mVolume = volume;
    handler->getParam().mId = id;
    // for internal tracking
    handler->getParam().mBuffer = it->second;
    handler->getParam().mNumberRepetition = numberRepetition;
    handler->mStateLock.unlock();
    sendCommand(mPlaybackHandler);
    if (!waitForCompletion(mPlaybackHandler, CLIENT_WAIT_TIMEOUT_MSEC)) {
        LOGE("timeout");
        return false;
    }
    return handler->mResult;
}

void RemoteAudio::stopPlayback()
{
    doStop(mPlaybackHandler, AudioProtocol::ECmdStopPlayback);
}

bool RemoteAudio::waitForPlaybackCompletion()
{
    return waitForPlaybackOrRecordingCompletion(mPlaybackHandler);
}

bool RemoteAudio::startRecording(bool stereo, int samplingF, int mode, int volume,
        android::sp<Buffer>& buffer)
{
    CommandHandler* handler = reinterpret_cast<CommandHandler*>(mRecordingHandler.get());
    handler->mStateLock.lock();
    if (handler->mActive) {
        LOGE("busy");
        handler->mStateLock.unlock();
        return false;
    }
    handler->mActive = true;
    handler->getParam().mStereo = stereo;
    handler->getParam().mSamplingF = samplingF;
    handler->getParam().mMode = mode;
    handler->getParam().mVolume = volume;
    handler->getParam().mBuffer = buffer;
    handler->mStateLock.unlock();
    sendCommand(mRecordingHandler);
    if (!waitForCompletion(mRecordingHandler, CLIENT_WAIT_TIMEOUT_MSEC)) {
        LOGE("timeout");
        return false;
    }
    return handler->mResult;
}

bool RemoteAudio::waitForRecordingCompletion()
{
    return waitForPlaybackOrRecordingCompletion(mRecordingHandler);
}

void RemoteAudio::stopRecording()
{
    doStop(mRecordingHandler, AudioProtocol::ECmdStopRecording);
}

bool RemoteAudio::getDeviceInfo(android::String8& data)
{
    CommandHandler* handler = reinterpret_cast<CommandHandler*>(mDeviceInfoHandler.get());
    handler->mStateLock.lock();
    handler->mNotifyOnReply = true;
    handler->getParam().mExtra = &data;
    handler->mStateLock.unlock();
    sendCommand(mDeviceInfoHandler);

    // client blocked until reply comes from DUT
    if (!waitForCompletion(mDeviceInfoHandler, CLIENT_WAIT_TIMEOUT_MSEC)) {
        LOGE("timeout");
        return false;
    }
    return handler->mResult;
}

/** should be called before RemoteAudio is destroyed */
void RemoteAudio::release()
{
    android::sp<android::MessageHandler> command(new CommandHandler(*this, CommandHandler::EExit));
    sendCommand(command);
    join(); // wait for exit
    mSocket.release();
}

void RemoteAudio::CommandHandler::handleMessage(const android::Message& message)
{
    switch(message.what) {
    case EExit:
        LOGD("thread exit requested, will exit ");
        mResult = true;
        mThread.mExitRequested = true;
        mClientWait.post(); // client will not wait, but just do it.
        break;
    case AudioProtocol::ECmdDownload:
    case AudioProtocol::ECmdStartPlayback:
    case AudioProtocol::ECmdStopPlayback:
    case AudioProtocol::ECmdStartRecording:
    case AudioProtocol::ECmdStopRecording:
    case AudioProtocol::ECmdGetDeviceInfo:
    {
        mResult = (mThread.mCmds[message.what - AudioProtocol::ECmdStart]) \
                ->sendCommand(mParam);
        // no post for download and getdeviceinfo. Client blocked until reply comes with time-out
        if ((message.what != AudioProtocol::ECmdDownload) &&
            (message.what != AudioProtocol::ECmdGetDeviceInfo)    ) {
            mClientWait.post();
        }

    }
        break;

    }
}
