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

#define LOG_NDEBUG 0
#define LOG_TAG "AAudioTest"

#include <aaudio/AAudio.h>
#include <android/log.h>
#include <gtest/gtest.h>

#include "utils.h"

// Creates a builder, the caller takes ownership
static void create_stream_builder(AAudioStreamBuilder** aaudioBuilder) {
    aaudio_result_t result = AAudio_createStreamBuilder(aaudioBuilder);
    ASSERT_EQ(AAUDIO_OK, result);
    ASSERT_NE(nullptr, *aaudioBuilder);
}

enum class Expect { FAIL, SUCCEED, NOT_CRASH };

// Tries to open an audio stream using a primed Builder.
// Takes ownership of the Builder.
static void try_opening_audio_stream(AAudioStreamBuilder *aaudioBuilder, Expect expect) {
    // Create an AAudioStream using the Builder.
    AAudioStream *aaudioStream = nullptr;
    aaudio_result_t result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
    if (expect == Expect::FAIL) {
        ASSERT_NE(AAUDIO_OK, result);
        ASSERT_EQ(nullptr, aaudioStream);
    } else if (expect == Expect::SUCCEED) {
        ASSERT_EQ(AAUDIO_OK, result);
        ASSERT_NE(nullptr, aaudioStream);
    } else { // NOT_CRASH
        ASSERT_TRUE(((result < 0) && (aaudioStream == nullptr))
                || ((result == AAUDIO_OK) && (aaudioStream != nullptr)));
    }

    // Cleanup
    ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
    if (aaudioStream != nullptr) {
        ASSERT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
    }
}

// Test creating a default stream with specific devices
static void runtest_aaudio_devices(int32_t deviceId, Expect expect) {
    AAudioStreamBuilder *aaudioBuilder = nullptr;
    create_stream_builder(&aaudioBuilder);
    AAudioStreamBuilder_setDeviceId(aaudioBuilder, deviceId);
    try_opening_audio_stream(aaudioBuilder, expect);
}

TEST(test_aaudio, aaudio_stream_device_unspecified) {
    runtest_aaudio_devices(AAUDIO_UNSPECIFIED, Expect::NOT_CRASH);
}

/* FIXME - why can we open this device? What is an illegal deviceId?
TEST(test_aaudio, aaudio_stream_device_absurd) {
    runtest_aaudio_devices(19736459, true);
}
*/
/* FIXME review
TEST(test_aaudio, aaudio_stream_device_reasonable) {
    runtest_aaudio_devices(1, false);
}
*/

/* FIXME - why can we open this device? What is an illegal deviceId?
TEST(test_aaudio, aaudio_stream_device_negative) {
    runtest_aaudio_devices(-765, true);
}
*/

// Test creating a default stream with everything unspecified.
TEST(test_aaudio, aaudio_stream_unspecified) {
    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
    AAudioStreamBuilder *aaudioBuilder = nullptr;
    create_stream_builder(&aaudioBuilder);

    // Create an AAudioStream using the Builder.
    AAudioStream *aaudioStream = nullptr;
    ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
    ASSERT_NE(nullptr, aaudioStream);

    // Cleanup
    EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
    EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
}

class AAudioStreamBuilderSamplingRateTest : public ::testing::TestWithParam<int32_t> {
  public:
    static std::string getTestName(const ::testing::TestParamInfo<int32_t>& info) {
        return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
    }
  protected:
    static bool isValidSamplingRate(int32_t sr) {
        return sr == AAUDIO_UNSPECIFIED || (sr >= 8000 && sr <= 1000000);
    }
};

TEST_P(AAudioStreamBuilderSamplingRateTest, openStream) {
    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
    AAudioStreamBuilder *aaudioBuilder = nullptr;
    create_stream_builder(&aaudioBuilder);
    AAudioStreamBuilder_setSampleRate(aaudioBuilder, GetParam());
    try_opening_audio_stream(
            aaudioBuilder, isValidSamplingRate(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
}

INSTANTIATE_TEST_CASE_P(SR, AAudioStreamBuilderSamplingRateTest,
        ::testing::Values(
                // Commonly used values
                AAUDIO_UNSPECIFIED, 8000, 11025, 16000, 22050, 44100, 48000, 88200, 96000,
                176400, 192000, 384000,
                // Odd values
                AAUDIO_UNSPECIFIED - 1, AAUDIO_UNSPECIFIED + 1, 1234, 10000000),
        &AAudioStreamBuilderSamplingRateTest::getTestName);

class AAudioStreamBuilderChannelCountTest : public ::testing::TestWithParam<int32_t> {
  public:
    static std::string getTestName(const ::testing::TestParamInfo<int32_t>& info) {
        return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
    }
  protected:
    static bool isValidChannelCount(int32_t cc) {
        return cc == AAUDIO_UNSPECIFIED || (cc >= 1 && cc <= 8);
    }
};

TEST_P(AAudioStreamBuilderChannelCountTest, openStream) {
    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
    AAudioStreamBuilder *aaudioBuilder = nullptr;
    create_stream_builder(&aaudioBuilder);
    AAudioStreamBuilder_setChannelCount(aaudioBuilder, GetParam());
    try_opening_audio_stream(
            aaudioBuilder, isValidChannelCount(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
}

INSTANTIATE_TEST_CASE_P(CC, AAudioStreamBuilderChannelCountTest,
        ::testing::Values(
                // Reasonable values
                AAUDIO_UNSPECIFIED, 1, 2, 3, 4, 5, 6, 7, 8,
                // Odd values
                AAUDIO_UNSPECIFIED - 1, 9, 100, 1000000, 10000000),
        &AAudioStreamBuilderChannelCountTest::getTestName);

class AAudioStreamBuilderFormatTest : public ::testing::TestWithParam<aaudio_format_t> {
  public:
    static std::string getTestName(const ::testing::TestParamInfo<aaudio_format_t>& info) {
        return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
    }
  protected:
    static bool isValidFormat(aaudio_format_t f) {
        switch (f) {
            case AAUDIO_FORMAT_UNSPECIFIED:
            case AAUDIO_FORMAT_PCM_I16:
            case AAUDIO_FORMAT_PCM_FLOAT:
                return true;
        }
        return false;
    }
};

TEST_P(AAudioStreamBuilderFormatTest, openStream) {
    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
    AAudioStreamBuilder *aaudioBuilder = nullptr;
    create_stream_builder(&aaudioBuilder);
    AAudioStreamBuilder_setFormat(aaudioBuilder, GetParam());
    try_opening_audio_stream(
            aaudioBuilder, isValidFormat(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
}

INSTANTIATE_TEST_CASE_P(F, AAudioStreamBuilderFormatTest,
        ::testing::Values(
                // Reasonable values
                AAUDIO_FORMAT_UNSPECIFIED, AAUDIO_FORMAT_PCM_I16, AAUDIO_FORMAT_PCM_FLOAT,
                // Odd values
                AAUDIO_FORMAT_INVALID, AAUDIO_FORMAT_INVALID - 1, 100, 1000000, 10000000),
        &AAudioStreamBuilderFormatTest::getTestName);

class AAudioStreamBuilderSharingModeTest : public ::testing::TestWithParam<aaudio_sharing_mode_t> {
  public:
    static std::string getTestName(const ::testing::TestParamInfo<aaudio_sharing_mode_t>& info) {
        return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
    }
  protected:
    static bool isValidSharingMode(aaudio_sharing_mode_t f) {
        return f == AAUDIO_SHARING_MODE_SHARED || f == AAUDIO_SHARING_MODE_EXCLUSIVE;
    }
};

TEST_P(AAudioStreamBuilderSharingModeTest, openStream) {
    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
    AAudioStreamBuilder *aaudioBuilder = nullptr;
    create_stream_builder(&aaudioBuilder);
    AAudioStreamBuilder_setFormat(aaudioBuilder, GetParam());
    try_opening_audio_stream(
            aaudioBuilder, isValidSharingMode(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
}

INSTANTIATE_TEST_CASE_P(SM, AAudioStreamBuilderSharingModeTest,
        ::testing::Values(
                // Reasonable values
                AAUDIO_SHARING_MODE_SHARED, AAUDIO_SHARING_MODE_EXCLUSIVE,
                // Odd values
                -1, 100, 1000000, 10000000),
        &AAudioStreamBuilderSharingModeTest::getTestName);

class AAudioStreamBuilderDirectionTest : public ::testing::TestWithParam<aaudio_direction_t> {
  public:
    static std::string getTestName(const ::testing::TestParamInfo<aaudio_direction_t>& info) {
        return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
    }
  protected:
    static bool isValidSharingMode(aaudio_direction_t f) {
        return f == AAUDIO_DIRECTION_OUTPUT || f == AAUDIO_DIRECTION_INPUT;
    }
};

TEST_P(AAudioStreamBuilderDirectionTest, openStream) {
    if (GetParam() == AAUDIO_DIRECTION_OUTPUT
            && !deviceSupportsFeature(FEATURE_PLAYBACK)) return;
    if (GetParam() == AAUDIO_DIRECTION_INPUT
            && !deviceSupportsFeature(FEATURE_RECORDING)) return;
    AAudioStreamBuilder *aaudioBuilder = nullptr;
    create_stream_builder(&aaudioBuilder);
    AAudioStreamBuilder_setFormat(aaudioBuilder, GetParam());
    try_opening_audio_stream(
            aaudioBuilder, isValidSharingMode(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
}

INSTANTIATE_TEST_CASE_P(SD, AAudioStreamBuilderDirectionTest,
        ::testing::Values(
                // Reasonable values
                AAUDIO_DIRECTION_OUTPUT, AAUDIO_DIRECTION_INPUT,
                // Odd values
                -1, 100, 1000000, 10000000),
        &AAudioStreamBuilderDirectionTest::getTestName);

class AAudioStreamBuilderBufferCapacityTest : public ::testing::TestWithParam<int32_t> {
  public:
    static std::string getTestName(const ::testing::TestParamInfo<int32_t>& info) {
        return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
    }
  protected:
    // There is no hard defined limit, the actual maximum capacity depends
    // on the implementation.
    static bool isValidCapacity(int32_t bc) {
        return bc == AAUDIO_UNSPECIFIED || bc >= 0;
    }
};

TEST_P(AAudioStreamBuilderBufferCapacityTest, openStream) {
    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
    AAudioStreamBuilder *aaudioBuilder = nullptr;
    create_stream_builder(&aaudioBuilder);
    AAudioStreamBuilder_setBufferCapacityInFrames(aaudioBuilder, GetParam());
    try_opening_audio_stream(
            aaudioBuilder, isValidCapacity(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
}

INSTANTIATE_TEST_CASE_P(BC, AAudioStreamBuilderBufferCapacityTest,
        ::testing::Values(
                // Reasonable values that should not fail
                AAUDIO_UNSPECIFIED, 8 * 192, 2 * 1024,
                // Odd values
                AAUDIO_UNSPECIFIED - 1),
        &AAudioStreamBuilderBufferCapacityTest::getTestName);

class AAudioStreamBuilderPerfModeTest : public ::testing::TestWithParam<aaudio_performance_mode_t> {
  public:
    static std::string getTestName(const ::testing::TestParamInfo<aaudio_performance_mode_t>& info) {
        return info.param >= 0 ? std::to_string(info.param) : "_" + std::to_string(-info.param);
    }
  protected:
    static bool isValidPerfMode(aaudio_performance_mode_t pm) {
        switch (pm) {
            case AAUDIO_PERFORMANCE_MODE_NONE:
            case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
            case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
                return true;
        }
        return false;
    }
};

TEST_P(AAudioStreamBuilderPerfModeTest, openStream) {
    if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
    AAudioStreamBuilder *aaudioBuilder = nullptr;
    create_stream_builder(&aaudioBuilder);
    AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, GetParam());
    try_opening_audio_stream(
            aaudioBuilder, isValidPerfMode(GetParam()) ? Expect::SUCCEED : Expect::FAIL);
}

INSTANTIATE_TEST_CASE_P(PM, AAudioStreamBuilderPerfModeTest,
        ::testing::Values(
                // Reasonable values
                AAUDIO_PERFORMANCE_MODE_NONE,
                AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
                AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
                // Odd values
                AAUDIO_UNSPECIFIED - 1, AAUDIO_UNSPECIFIED, 100, 1000000, 10000000),
        &AAudioStreamBuilderPerfModeTest::getTestName);
