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

#ifndef OBOE_FILTER_AUDIO_STREAM_H
#define OBOE_FILTER_AUDIO_STREAM_H

#include <memory>
#include <oboe/AudioStream.h>
#include "DataConversionFlowGraph.h"

namespace oboe {

/**
 * An AudioStream that wraps another AudioStream and provides audio data conversion.
 * Operations may include channel conversion, data format conversion and/or sample rate conversion.
 */
class FilterAudioStream : public AudioStream, AudioStreamCallback {
public:

    /**
     * Construct an `AudioStream` using the given `AudioStreamBuilder` and a child AudioStream.
     *
     * This should only be called internally by AudioStreamBuilder.
     * Ownership of childStream will be passed to this object.
     *
     * @param builder containing all the stream's attributes
     */
    FilterAudioStream(const AudioStreamBuilder &builder, AudioStream *childStream)
    : AudioStream(builder)
    , mChildStream(childStream) {
        // Intercept the callback if used.
        if (builder.getCallback() != nullptr) {
            mStreamCallback = mChildStream->swapCallback(this);
        } else {
            const int size = childStream->getFramesPerBurst() * childStream->getBytesPerFrame();
            mBlockingBuffer = std::make_unique<uint8_t[]>(size);
        }

        // Copy parameters that may not match builder.
        mBufferCapacityInFrames = mChildStream->getBufferCapacityInFrames();
        mPerformanceMode = mChildStream->getPerformanceMode();
    }

    virtual ~FilterAudioStream() = default;

    AudioStream *getChildStream() const {
        return mChildStream.get();
    }

    Result configureFlowGraph();

    // Close child and parent.
    Result close()  override {
        const Result result1 = mChildStream->close();
        const Result result2 = AudioStream::close();
        return (result1 != Result::OK ? result1 : result2);
    }

    /**
     * Start the stream asynchronously. Returns immediately (does not block). Equivalent to calling
     * `start(0)`.
     */
    Result requestStart() override {
        return mChildStream->requestStart();
    }

    /**
     * Pause the stream asynchronously. Returns immediately (does not block). Equivalent to calling
     * `pause(0)`.
     */
    Result requestPause() override {
        return mChildStream->requestPause();
    }

    /**
     * Flush the stream asynchronously. Returns immediately (does not block). Equivalent to calling
     * `flush(0)`.
     */
    Result requestFlush() override {
        return mChildStream->requestFlush();
    }

    /**
     * Stop the stream asynchronously. Returns immediately (does not block). Equivalent to calling
     * `stop(0)`.
     */
    Result requestStop() override {
        return mChildStream->requestStop();
    }

    ResultWithValue<int32_t> read(void *buffer,
            int32_t numFrames,
            int64_t timeoutNanoseconds) override;

    ResultWithValue<int32_t> write(const void *buffer,
            int32_t numFrames,
            int64_t timeoutNanoseconds) override;

    StreamState getState() const override {
        return mChildStream->getState();
    }

    Result waitForStateChange(
            StreamState inputState,
            StreamState *nextState,
            int64_t timeoutNanoseconds) override {
        return mChildStream->waitForStateChange(inputState, nextState, timeoutNanoseconds);
    }

    bool isXRunCountSupported() const override {
        return mChildStream->isXRunCountSupported();
    }

    int32_t getFramesPerBurst() override {
        return mChildStream->getFramesPerBurst();
    }

    AudioApi getAudioApi() const override {
        return mChildStream->getAudioApi();
    }

    void updateFramesWritten() override {
        // TODO for output, just count local writes?
        mFramesWritten = static_cast<int64_t>(mChildStream->getFramesWritten() * mRateScaler);
    }

    void updateFramesRead() override {
        // TODO for input, just count local reads?
        mFramesRead = static_cast<int64_t>(mChildStream->getFramesRead() * mRateScaler);
    }

    void *getUnderlyingStream() const  override {
        return mChildStream->getUnderlyingStream();
    }

    ResultWithValue<int32_t> setBufferSizeInFrames(int32_t requestedFrames) override {
        return mChildStream->setBufferSizeInFrames(requestedFrames);
    }

    int32_t getBufferSizeInFrames() override {
        mBufferSizeInFrames = mChildStream->getBufferSizeInFrames();
        return mBufferSizeInFrames;
    }

    ResultWithValue<int32_t> getXRunCount() const override {
        return mChildStream->getXRunCount();
    }

    ResultWithValue<double> calculateLatencyMillis() override {
        // This will automatically include the latency of the flowgraph?
        return mChildStream->calculateLatencyMillis();
    }

    Result getTimestamp(clockid_t clockId,
            int64_t *framePosition,
            int64_t *timeNanoseconds) override {
        int64_t childPosition = 0;
        Result result = mChildStream->getTimestamp(clockId, &childPosition, timeNanoseconds);
        *framePosition = childPosition * mRateScaler;
        return result;
    }

    DataCallbackResult onAudioReady(AudioStream *oboeStream,
            void *audioData,
            int32_t numFrames) override {
        int32_t framesProcessed;
        if (oboeStream->getDirection() == Direction::Output) {
            framesProcessed = mFlowGraph->read(audioData, numFrames, 0 /* timeout */);
        } else {
            framesProcessed = mFlowGraph->write(audioData, numFrames);
        }
        return (framesProcessed < numFrames)
                ? DataCallbackResult::Stop
                : mFlowGraph->getDataCallbackResult();
    }

    void onErrorBeforeClose(AudioStream *oboeStream, Result error) override {
        if (mStreamCallback != nullptr) {
            mStreamCallback->onErrorBeforeClose(this, error);
        }
    }

    void onErrorAfterClose(AudioStream *oboeStream, Result error) override {
        // Close this parent stream because the callback will only close the child.
        AudioStream::close();
        if (mStreamCallback != nullptr) {
            mStreamCallback->onErrorAfterClose(this, error);
        }
    }

private:

    std::unique_ptr<AudioStream>             mChildStream; // this stream wraps the child stream
    std::unique_ptr<DataConversionFlowGraph> mFlowGraph; // for converting data
    std::unique_ptr<uint8_t[]>               mBlockingBuffer; // temp buffer for write()
    double                                   mRateScaler = 1.0; // ratio parent/child sample rates
};

} // oboe

#endif //OBOE_FILTER_AUDIO_STREAM_H
