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

#include <memory>

#include "oboe/Oboe.h"

#include "common/OboeDebug.h"
#include "oboe/AudioClock.h"
#include "opensles/AudioStreamBuffered.h"

namespace oboe {

constexpr int kDefaultBurstsPerBuffer = 16;  // arbitrary, allows dynamic latency tuning
constexpr int kMinBurstsPerBuffer     = 4;  // arbitrary, allows dynamic latency tuning
constexpr int kMinFramesPerBuffer     = 48 * 32; // arbitrary

/*
 * AudioStream with a FifoBuffer
 */
AudioStreamBuffered::AudioStreamBuffered(const AudioStreamBuilder &builder)
        : AudioStream(builder) {
}

void AudioStreamBuffered::allocateFifo() {
    // If the caller does not provide a callback use our own internal
    // callback that reads data from the FIFO.
    if (usingFIFO()) {
        // FIFO is configured with the same format and channels as the stream.
        int32_t capacityFrames = getBufferCapacityInFrames();
        if (capacityFrames == oboe::kUnspecified) {
            capacityFrames = getFramesPerBurst() * kDefaultBurstsPerBuffer;
        } else {
            int32_t minFramesPerBufferByBursts = getFramesPerBurst() * kMinBurstsPerBuffer;
            if (capacityFrames <= minFramesPerBufferByBursts) {
                capacityFrames = minFramesPerBufferByBursts;
            } else {
                capacityFrames = std::max(kMinFramesPerBuffer, capacityFrames);
                // round up to nearest burst
                int32_t numBursts = (capacityFrames + getFramesPerBurst() - 1)
                        / getFramesPerBurst();
                capacityFrames = numBursts * getFramesPerBurst();
            }
        }

        mFifoBuffer = std::make_unique<FifoBuffer>(getBytesPerFrame(), capacityFrames);
        mBufferCapacityInFrames = capacityFrames;
        mBufferSizeInFrames = mBufferCapacityInFrames;
    }
}

void AudioStreamBuffered::updateFramesWritten() {
    if (mFifoBuffer) {
        mFramesWritten = static_cast<int64_t>(mFifoBuffer->getWriteCounter());
    } // or else it will get updated by processBufferCallback()
}

void AudioStreamBuffered::updateFramesRead() {
    if (mFifoBuffer) {
        mFramesRead = static_cast<int64_t>(mFifoBuffer->getReadCounter());
    } // or else it will get updated by processBufferCallback()
}

// This is called by the OpenSL ES callback to read or write the back end of the FIFO.
DataCallbackResult AudioStreamBuffered::onDefaultCallback(void *audioData, int numFrames) {
    int32_t framesTransferred  = 0;

    if (getDirection() == oboe::Direction::Output) {
        // Read from the FIFO and write to audioData, clear part of buffer if not enough data.
        framesTransferred = mFifoBuffer->readNow(audioData, numFrames);
    } else {
        // Read from audioData and write to the FIFO
        framesTransferred = mFifoBuffer->write(audioData, numFrames); // There is no writeNow()
    }

    if (framesTransferred < numFrames) {
        LOGD("AudioStreamBuffered::%s(): xrun! framesTransferred = %d, numFrames = %d",
                __func__, framesTransferred, numFrames);
        // TODO If we do not allow FIFO to wrap then our timestamps will drift when there is an XRun!
        incrementXRunCount();
    }
    markCallbackTime(static_cast<int32_t>(numFrames)); // so foreground knows how long to wait.
    return DataCallbackResult::Continue;
}

void AudioStreamBuffered::markCallbackTime(int32_t numFrames) {
    mLastBackgroundSize = numFrames;
    mBackgroundRanAtNanoseconds = AudioClock::getNanoseconds();
}

int64_t AudioStreamBuffered::predictNextCallbackTime() {
    if (mBackgroundRanAtNanoseconds == 0) {
        return 0;
    }
    int64_t nanosPerBuffer = (kNanosPerSecond * mLastBackgroundSize) / getSampleRate();
    const int64_t margin = 200 * kNanosPerMicrosecond; // arbitrary delay so we wake up just after
    return mBackgroundRanAtNanoseconds + nanosPerBuffer + margin;
}

// Common code for read/write.
// @return Result::OK with frames read/written, or Result::Error*
ResultWithValue<int32_t> AudioStreamBuffered::transfer(
        void *readBuffer,
        const void *writeBuffer,
        int32_t numFrames,
        int64_t timeoutNanoseconds) {
    // Validate arguments.
    if (readBuffer != nullptr && writeBuffer != nullptr) {
        LOGE("AudioStreamBuffered::%s(): both buffers are not NULL", __func__);
        return ResultWithValue<int32_t>(Result::ErrorInternal);
    }
    if (getDirection() == Direction::Input && readBuffer == nullptr) {
        LOGE("AudioStreamBuffered::%s(): readBuffer is NULL", __func__);
        return ResultWithValue<int32_t>(Result::ErrorNull);
    }
    if (getDirection() == Direction::Output && writeBuffer == nullptr) {
        LOGE("AudioStreamBuffered::%s(): writeBuffer is NULL", __func__);
        return ResultWithValue<int32_t>(Result::ErrorNull);
    }
    if (numFrames < 0) {
        LOGE("AudioStreamBuffered::%s(): numFrames is negative", __func__);
        return ResultWithValue<int32_t>(Result::ErrorOutOfRange);
    } else if (numFrames == 0) {
        return ResultWithValue<int32_t>(numFrames);
    }
    if (timeoutNanoseconds < 0) {
        LOGE("AudioStreamBuffered::%s(): timeoutNanoseconds is negative", __func__);
        return ResultWithValue<int32_t>(Result::ErrorOutOfRange);
    }

    int32_t result = 0;
    uint8_t *readData = reinterpret_cast<uint8_t *>(readBuffer);
    const uint8_t *writeData = reinterpret_cast<const uint8_t *>(writeBuffer);
    int32_t framesLeft = numFrames;
    int64_t timeToQuit = 0;
    bool repeat = true;

    // Calculate when to timeout.
    if (timeoutNanoseconds > 0) {
        timeToQuit = AudioClock::getNanoseconds() + timeoutNanoseconds;
    }

    // Loop until we get the data, or we have an error, or we timeout.
    do {
        // read or write
        if (getDirection() == Direction::Input) {
            result = mFifoBuffer->read(readData, framesLeft);
            if (result > 0) {
                readData += mFifoBuffer->convertFramesToBytes(result);
                framesLeft -= result;
            }
        } else {
            // between zero and capacity
            uint32_t fullFrames = mFifoBuffer->getFullFramesAvailable();
            // Do not write above threshold size.
            int32_t emptyFrames = getBufferSizeInFrames() - static_cast<int32_t>(fullFrames);
            int32_t framesToWrite = std::max(0, std::min(framesLeft, emptyFrames));
            result = mFifoBuffer->write(writeData, framesToWrite);
            if (result > 0) {
                writeData += mFifoBuffer->convertFramesToBytes(result);
                framesLeft -= result;
            }
        }

        // If we need more data then sleep and try again.
        if (framesLeft > 0 && result >= 0 && timeoutNanoseconds > 0) {
            int64_t timeNow = AudioClock::getNanoseconds();
            if (timeNow >= timeToQuit) {
                LOGE("AudioStreamBuffered::%s(): TIMEOUT", __func__);
                repeat = false; // TIMEOUT
            } else {
                // Figure out how long to sleep.
                int64_t sleepForNanos;
                int64_t wakeTimeNanos = predictNextCallbackTime();
                if (wakeTimeNanos <= 0) {
                    // No estimate available. Sleep for one burst.
                    sleepForNanos = (getFramesPerBurst() * kNanosPerSecond) / getSampleRate();
                } else {
                    // Don't sleep past timeout.
                    if (wakeTimeNanos > timeToQuit) {
                        wakeTimeNanos = timeToQuit;
                    }
                    sleepForNanos = wakeTimeNanos - timeNow;
                    // Avoid rapid loop with no sleep.
                    const int64_t minSleepTime = kNanosPerMillisecond; // arbitrary
                    if (sleepForNanos < minSleepTime) {
                        sleepForNanos = minSleepTime;
                    }
                }

                AudioClock::sleepForNanos(sleepForNanos);
            }

        } else {
            repeat = false;
        }
    } while(repeat);

    if (result < 0) {
        return ResultWithValue<int32_t>(static_cast<Result>(result));
    } else {
        int32_t framesWritten = numFrames - framesLeft;
        return ResultWithValue<int32_t>(framesWritten);
    }
}

// Write to the FIFO so the callback can read from it.
ResultWithValue<int32_t> AudioStreamBuffered::write(const void *buffer,
                                   int32_t numFrames,
                                   int64_t timeoutNanoseconds) {
    if (getState() == StreamState::Closed){
        return ResultWithValue<int32_t>(Result::ErrorClosed);
    }

    if (getDirection() == Direction::Input) {
        return ResultWithValue<int32_t>(Result::ErrorUnavailable); // TODO review, better error code?
    }
    Result result = updateServiceFrameCounter();
    if (result != Result::OK) return ResultWithValue<int32_t>(static_cast<Result>(result));
    return transfer(nullptr, buffer, numFrames, timeoutNanoseconds);
}

// Read data from the FIFO that was written by the callback.
ResultWithValue<int32_t> AudioStreamBuffered::read(void *buffer,
                                  int32_t numFrames,
                                  int64_t timeoutNanoseconds) {
    if (getState() == StreamState::Closed){
        return ResultWithValue<int32_t>(Result::ErrorClosed);
    }

    if (getDirection() == Direction::Output) {
        return ResultWithValue<int32_t>(Result::ErrorUnavailable); // TODO review, better error code?
    }
    Result result = updateServiceFrameCounter();
    if (result != Result::OK) return ResultWithValue<int32_t>(static_cast<Result>(result));
    return transfer(buffer, nullptr, numFrames, timeoutNanoseconds);
}

// Only supported when we are not using a callback.
ResultWithValue<int32_t> AudioStreamBuffered::setBufferSizeInFrames(int32_t requestedFrames)
{
    if (getState() == StreamState::Closed){
        return ResultWithValue<int32_t>(Result::ErrorClosed);
    }

    if (!mFifoBuffer) {
        return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
    }

    if (requestedFrames > mFifoBuffer->getBufferCapacityInFrames()) {
        requestedFrames = mFifoBuffer->getBufferCapacityInFrames();
    } else if (requestedFrames < getFramesPerBurst()) {
        requestedFrames = getFramesPerBurst();
    }
    mBufferSizeInFrames = requestedFrames;
    return ResultWithValue<int32_t>(requestedFrames);
}

int32_t AudioStreamBuffered::getBufferCapacityInFrames() const {
    if (mFifoBuffer) {
        return mFifoBuffer->getBufferCapacityInFrames();
    } else {
        return AudioStream::getBufferCapacityInFrames();
    }
}

bool AudioStreamBuffered::isXRunCountSupported() const {
    // XRun count is only supported if we're using blocking I/O (not callbacks)
    return (!isDataCallbackSpecified());
}

} // namespace oboe
