/*
 * Copyright (C) 2016 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.
 */

#define LOG_TAG "AAudioService"
//#define LOG_NDEBUG 0
#include <utils/Log.h>

#include <mutex>

#include "binding/IAAudioService.h"
#include "binding/AAudioServiceMessage.h"
#include "utility/AudioClock.h"

#include "AAudioServiceStreamBase.h"
#include "TimestampScheduler.h"

using namespace android;  // TODO just import names needed
using namespace aaudio;   // TODO just import names needed

/**
 * Base class for streams in the service.
 * @return
 */

AAudioServiceStreamBase::AAudioServiceStreamBase()
        : mUpMessageQueue(nullptr)
        , mAAudioThread() {
}

AAudioServiceStreamBase::~AAudioServiceStreamBase() {
    close();
}

aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request,
                     aaudio::AAudioStreamConfiguration &configurationOutput) {
    std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
    if (mUpMessageQueue != nullptr) {
        return AAUDIO_ERROR_INVALID_STATE;
    } else {
        mUpMessageQueue = new SharedRingBuffer();
        return mUpMessageQueue->allocate(sizeof(AAudioServiceMessage), QUEUE_UP_CAPACITY_COMMANDS);
    }
}

aaudio_result_t AAudioServiceStreamBase::close() {
    std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
    delete mUpMessageQueue;
    mUpMessageQueue = nullptr;
    return AAUDIO_OK;
}

aaudio_result_t AAudioServiceStreamBase::start() {
    sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
    mState = AAUDIO_STREAM_STATE_STARTED;
    mThreadEnabled.store(true);
    return mAAudioThread.start(this);
}

aaudio_result_t AAudioServiceStreamBase::pause() {

    sendCurrentTimestamp();
    mThreadEnabled.store(false);
    aaudio_result_t result = mAAudioThread.stop();
    if (result != AAUDIO_OK) {
        processError();
        return result;
    }
    sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
    mState = AAUDIO_STREAM_STATE_PAUSED;
    return result;
}

// implement Runnable
void AAudioServiceStreamBase::run() {
    ALOGD("AAudioServiceStreamMMAP::run() entering ----------------");
    TimestampScheduler timestampScheduler;
    timestampScheduler.setBurstPeriod(mFramesPerBurst, mSampleRate);
    timestampScheduler.start(AudioClock::getNanoseconds());
    int64_t nextTime = timestampScheduler.nextAbsoluteTime();
    while(mThreadEnabled.load()) {
        if (AudioClock::getNanoseconds() >= nextTime) {
            aaudio_result_t result = sendCurrentTimestamp();
            if (result != AAUDIO_OK) {
                break;
            }
            nextTime = timestampScheduler.nextAbsoluteTime();
        } else  {
            // Sleep until it is time to send the next timestamp.
            AudioClock::sleepUntilNanoTime(nextTime);
        }
    }
    ALOGD("AAudioServiceStreamMMAP::run() exiting ----------------");
}

void AAudioServiceStreamBase::processError() {
    sendServiceEvent(AAUDIO_SERVICE_EVENT_DISCONNECTED);
}

aaudio_result_t AAudioServiceStreamBase::sendServiceEvent(aaudio_service_event_t event,
                                               double  dataDouble,
                                               int64_t dataLong) {
    AAudioServiceMessage command;
    command.what = AAudioServiceMessage::code::EVENT;
    command.event.event = event;
    command.event.dataDouble = dataDouble;
    command.event.dataLong = dataLong;
    return writeUpMessageQueue(&command);
}

aaudio_result_t AAudioServiceStreamBase::writeUpMessageQueue(AAudioServiceMessage *command) {
    std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
    int32_t count = mUpMessageQueue->getFifoBuffer()->write(command, 1);
    if (count != 1) {
        ALOGE("writeUpMessageQueue(): Queue full. Did client die?");
        return AAUDIO_ERROR_WOULD_BLOCK;
    } else {
        return AAUDIO_OK;
    }
}

aaudio_result_t AAudioServiceStreamBase::sendCurrentTimestamp() {
    AAudioServiceMessage command;
    aaudio_result_t result = getFreeRunningPosition(&command.timestamp.position,
                                                    &command.timestamp.timestamp);
    if (result == AAUDIO_OK) {
        command.what = AAudioServiceMessage::code::TIMESTAMP;
        result = writeUpMessageQueue(&command);
    }
    return result;
}


/**
 * Get an immutable description of the in-memory queues
 * used to communicate with the underlying HAL or Service.
 */
aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
    // Gather information on the message queue.
    mUpMessageQueue->fillParcelable(parcelable,
                                    parcelable.mUpMessageQueueParcelable);
    return getDownDataDescription(parcelable);
}