/*
 * Copyright 2021 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 <atomic>
#include <tuple>

#include <gtest/gtest.h>
#include <oboe/Oboe.h>


// Test returning DataCallbackResult::Stop from a callback.
using namespace oboe;

static constexpr int kTimeoutInNanos = 500 * kNanosPerMillisecond;

class ReturnStopCallback : public AudioStreamDataCallback {
public:
    DataCallbackResult onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numFrames) override {
        return (++callbackCount < kMaxCallbacks) ? DataCallbackResult::Continue : DataCallbackResult::Stop;
    }

    void reset() {
        callbackCount = 0;
    }

    int getMaxCallbacks() const { return kMaxCallbacks; }

    std::atomic<int> callbackCount{0};
    
private:
    // I get strange linker errors with GTest if I try to reference this directly.
    static constexpr int kMaxCallbacks = 40;
};

using StreamReturnStopParams = std::tuple<Direction, AudioApi, PerformanceMode, bool>;

class StreamReturnStop : public ::testing::Test,
                         public ::testing::WithParamInterface<StreamReturnStopParams> {

protected:
    void TearDown() override;

    AudioStreamBuilder mBuilder;
    AudioStream *mStream = nullptr;
};

void StreamReturnStop::TearDown() {
    if (mStream != nullptr) {
        mStream->close();
        mStream = nullptr;
    }
}

TEST_P(StreamReturnStop, VerifyStreamReturnStop) {
    const Direction direction = std::get<0>(GetParam());
    const AudioApi audioApi = std::get<1>(GetParam());
    const PerformanceMode performanceMode = std::get<2>(GetParam());
    const bool useRequestStart = std::get<3>(GetParam());

    ReturnStopCallback *callback = new ReturnStopCallback();
    mBuilder.setDirection(direction)
            ->setFormat(AudioFormat::I16)
            ->setPerformanceMode(performanceMode)
            ->setDataCallback(callback);
    if (mBuilder.isAAudioRecommended()) {
        mBuilder.setAudioApi(audioApi);
    }
    mStream = nullptr;
    Result r = mBuilder.openStream(&mStream);
    ASSERT_EQ(r, Result::OK) << "Failed to open stream. " << convertToText(r);

    // Start and stop several times.
    for (int i = 0; i < 3; i++) {
        callback->reset();
        // Oboe has two ways to start a stream.
        if (useRequestStart) {
            r = mStream->requestStart();
        } else {
            r = mStream->start();
        }
        ASSERT_EQ(r, Result::OK) << "Failed to start stream. " << convertToText(r);
    
        // Wait for callbacks to complete.
        const int kMaxCallbackPeriodMillis = 500;
        const int kPollPeriodMillis = 20;
        int timeout = 2 * callback->getMaxCallbacks() * kMaxCallbackPeriodMillis / kPollPeriodMillis;
        do {
            usleep(kPollPeriodMillis * 1000);
        } while (callback->callbackCount < callback->getMaxCallbacks() && timeout-- > 0);
        EXPECT_GT(timeout, 0) << "timed out waiting for enough callbacks";
        
        StreamState next = StreamState::Unknown;
        r = mStream->waitForStateChange(StreamState::Started, &next, kTimeoutInNanos);
        EXPECT_EQ(r, Result::OK) << "waitForStateChange(Started) timed out. " << convertToText(r);
        r = mStream->waitForStateChange(StreamState::Stopping, &next, kTimeoutInNanos);
        EXPECT_EQ(r, Result::OK) << "waitForStateChange(Stopping) timed out. " << convertToText(r);
        EXPECT_EQ(next, StreamState::Stopped) << "Stream not in state Stopped, was " << convertToText(next);
        
        EXPECT_EQ(callback->callbackCount, callback->getMaxCallbacks()) << "Too many callbacks = " << callback->callbackCount;

        const int kOboeStartStopSleepMSec = 10;
        usleep(kOboeStartStopSleepMSec * 1000); // avoid race condition in emulator
    }

    ASSERT_EQ(Result::OK, mStream->close());
}

INSTANTIATE_TEST_SUITE_P(
        StreamReturnStopTest,
        StreamReturnStop,
        ::testing::Values(
                // Last boolean is true if requestStart() should be called instead of start().
                StreamReturnStopParams({Direction::Output, AudioApi::AAudio, PerformanceMode::LowLatency, true}),
                StreamReturnStopParams({Direction::Output, AudioApi::AAudio, PerformanceMode::LowLatency, false}),
                StreamReturnStopParams({Direction::Output, AudioApi::AAudio, PerformanceMode::None, true}),
                StreamReturnStopParams({Direction::Output, AudioApi::AAudio, PerformanceMode::None, false}),
                StreamReturnStopParams({Direction::Output, AudioApi::OpenSLES, PerformanceMode::LowLatency, true}),
                StreamReturnStopParams({Direction::Output, AudioApi::OpenSLES, PerformanceMode::LowLatency, false}),
                StreamReturnStopParams({Direction::Input, AudioApi::AAudio, PerformanceMode::LowLatency, true}),
                StreamReturnStopParams({Direction::Input, AudioApi::AAudio, PerformanceMode::LowLatency, false})
                )
        );
