/*
 * Copyright (C) 2017 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 <algorithm>
#include <mutex>
#include <vector>

#include "core/AudioStreamBuilder.h"
#include "AAudioServiceEndpoint.h"
#include "AAudioServiceStreamShared.h"

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

#define MIN_TIMEOUT_NANOS        (1000 * AAUDIO_NANOS_PER_MILLISECOND)

// Wait at least this many times longer than the operation should take.
#define MIN_TIMEOUT_OPERATIONS    4

// The mStreamInternal will use a service interface that does not go through Binder.
AAudioServiceEndpoint::AAudioServiceEndpoint(AAudioService &audioService)
        : mStreamInternal(audioService, true)
        {
}

AAudioServiceEndpoint::~AAudioServiceEndpoint() {
}

// Set up an EXCLUSIVE MMAP stream that will be shared.
aaudio_result_t AAudioServiceEndpoint::open(int32_t deviceId, aaudio_direction_t direction) {
    AudioStreamBuilder builder;
    builder.setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
    builder.setDeviceId(deviceId);
    builder.setDirection(direction);
    aaudio_result_t result = mStreamInternal.open(builder);
    if (result == AAUDIO_OK) {
        mMixer.allocate(mStreamInternal.getSamplesPerFrame(), mStreamInternal.getFramesPerBurst());
    }
    return result;
}

aaudio_result_t AAudioServiceEndpoint::close() {
    return mStreamInternal.close();
}

// TODO, maybe use an interface to reduce exposure
aaudio_result_t AAudioServiceEndpoint::registerStream(AAudioServiceStreamShared *sharedStream) {
    ALOGD("AAudioServiceEndpoint::registerStream(%p)", sharedStream);
    // TODO use real-time technique to avoid mutex, eg. atomic command FIFO
    std::lock_guard<std::mutex> lock(mLockStreams);
    mRegisteredStreams.push_back(sharedStream);
    return AAUDIO_OK;
}

aaudio_result_t AAudioServiceEndpoint::unregisterStream(AAudioServiceStreamShared *sharedStream) {
    ALOGD("AAudioServiceEndpoint::unregisterStream(%p)", sharedStream);
    std::lock_guard<std::mutex> lock(mLockStreams);
    mRegisteredStreams.erase(std::remove(mRegisteredStreams.begin(), mRegisteredStreams.end(), sharedStream),
              mRegisteredStreams.end());
    return AAUDIO_OK;
}

aaudio_result_t AAudioServiceEndpoint::startStream(AAudioServiceStreamShared *sharedStream) {
    // TODO use real-time technique to avoid mutex, eg. atomic command FIFO
    ALOGD("AAudioServiceEndpoint(): startStream() entering");
    std::lock_guard<std::mutex> lock(mLockStreams);
    mRunningStreams.push_back(sharedStream);
    if (mRunningStreams.size() == 1) {
        startMixer_l();
    }
    return AAUDIO_OK;
}

aaudio_result_t AAudioServiceEndpoint::stopStream(AAudioServiceStreamShared *sharedStream) {
    std::lock_guard<std::mutex> lock(mLockStreams);
    mRunningStreams.erase(std::remove(mRunningStreams.begin(), mRunningStreams.end(), sharedStream),
              mRunningStreams.end());
    if (mRunningStreams.size() == 0) {
        stopMixer_l();
    }
    return AAUDIO_OK;
}

static void *aaudio_mixer_thread_proc(void *context) {
    AAudioServiceEndpoint *stream = (AAudioServiceEndpoint *) context;
    //LOGD("AudioStreamAAudio(): oboe_callback_thread, stream = %p", stream);
    if (stream != NULL) {
        return stream->callbackLoop();
    } else {
        return NULL;
    }
}

// Render audio in the application callback and then write the data to the stream.
void *AAudioServiceEndpoint::callbackLoop() {
    aaudio_result_t result = AAUDIO_OK;

    ALOGD("AAudioServiceEndpoint(): callbackLoop() entering");

    result = mStreamInternal.requestStart();
    ALOGD("AAudioServiceEndpoint(): callbackLoop() after requestStart()  %d, isPlaying() = %d",
          result, (int) mStreamInternal.isPlaying());

    // result might be a frame count
    while (mCallbackEnabled.load() && mStreamInternal.isPlaying() && (result >= 0)) {
        // Mix data from each active stream.
        {
            mMixer.clear();
            std::lock_guard<std::mutex> lock(mLockStreams);
            for(AAudioServiceStreamShared *sharedStream : mRunningStreams) {
                FifoBuffer *fifo = sharedStream->getDataFifoBuffer();
                float volume = 0.5; // TODO get from system
                mMixer.mix(fifo, volume);
            }
        }

        // Write audio data to stream using a blocking write.
        ALOGD("AAudioServiceEndpoint(): callbackLoop() write(%d)", getFramesPerBurst());
        int64_t timeoutNanos = calculateReasonableTimeout(mStreamInternal.getFramesPerBurst());
        result = mStreamInternal.write(mMixer.getOutputBuffer(), getFramesPerBurst(), timeoutNanos);
        if (result == AAUDIO_ERROR_DISCONNECTED) {
            disconnectRegisteredStreams();
            break;
        } else if (result != getFramesPerBurst()) {
            ALOGW("AAudioServiceEndpoint(): callbackLoop() wrote %d / %d",
                  result, getFramesPerBurst());
            break;
        }
    }

    ALOGD("AAudioServiceEndpoint(): callbackLoop() exiting, result = %d, isPlaying() = %d",
          result, (int) mStreamInternal.isPlaying());

    result = mStreamInternal.requestStop();

    return NULL; // TODO review
}

aaudio_result_t AAudioServiceEndpoint::startMixer_l() {
    // Launch the callback loop thread.
    int64_t periodNanos = mStreamInternal.getFramesPerBurst()
                          * AAUDIO_NANOS_PER_SECOND
                          / getSampleRate();
    mCallbackEnabled.store(true);
    return mStreamInternal.createThread(periodNanos, aaudio_mixer_thread_proc, this);
}

aaudio_result_t AAudioServiceEndpoint::stopMixer_l() {
    mCallbackEnabled.store(false);
    return mStreamInternal.joinThread(NULL, calculateReasonableTimeout(mStreamInternal.getFramesPerBurst()));
}

// TODO Call method in AudioStreamInternal when that callback CL is merged.
int64_t AAudioServiceEndpoint::calculateReasonableTimeout(int32_t framesPerOperation) {

    // Wait for at least a second or some number of callbacks to join the thread.
    int64_t timeoutNanoseconds = (MIN_TIMEOUT_OPERATIONS * framesPerOperation * AAUDIO_NANOS_PER_SECOND)
                                 / getSampleRate();
    if (timeoutNanoseconds < MIN_TIMEOUT_NANOS) { // arbitrary number of seconds
        timeoutNanoseconds = MIN_TIMEOUT_NANOS;
    }
    return timeoutNanoseconds;
}

void AAudioServiceEndpoint::disconnectRegisteredStreams() {
    std::lock_guard<std::mutex> lock(mLockStreams);
    for(AAudioServiceStreamShared *sharedStream : mRunningStreams) {
        sharedStream->onStop();
    }
    mRunningStreams.clear();
    for(AAudioServiceStreamShared *sharedStream : mRegisteredStreams) {
        sharedStream->onDisconnect();
    }
    mRegisteredStreams.clear();
}
