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

#include <cassert>

#include "common/OboeDebug.h"
#include "oboe/AudioClock.h"
#include "oboe/AudioStreamBuilder.h"
#include "AudioOutputStreamOpenSLES.h"
#include "AudioStreamOpenSLES.h"
#include "OpenSLESUtilities.h"
#include "OutputMixerOpenSLES.h"

using namespace oboe;

static SLuint32 OpenSLES_convertOutputUsage(Usage oboeUsage) {
    SLuint32 openslStream;
    switch(oboeUsage) {
        case Usage::Media:
        case Usage::Game:
            openslStream = SL_ANDROID_STREAM_MEDIA;
            break;
        case Usage::VoiceCommunication:
        case Usage::VoiceCommunicationSignalling:
            openslStream = SL_ANDROID_STREAM_VOICE;
            break;
        case Usage::Alarm:
            openslStream = SL_ANDROID_STREAM_ALARM;
            break;
        case Usage::Notification:
        case Usage::NotificationEvent:
            openslStream = SL_ANDROID_STREAM_NOTIFICATION;
            break;
        case Usage::NotificationRingtone:
            openslStream = SL_ANDROID_STREAM_RING;
            break;
        case Usage::AssistanceAccessibility:
        case Usage::AssistanceNavigationGuidance:
        case Usage::AssistanceSonification:
        case Usage::Assistant:
        default:
            openslStream = SL_ANDROID_STREAM_SYSTEM;
            break;
    }
    return openslStream;
}

AudioOutputStreamOpenSLES::AudioOutputStreamOpenSLES(const AudioStreamBuilder &builder)
        : AudioStreamOpenSLES(builder) {
}

// These will wind up in <SLES/OpenSLES_Android.h>
constexpr int SL_ANDROID_SPEAKER_STEREO = (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);

constexpr int SL_ANDROID_SPEAKER_QUAD = (SL_ANDROID_SPEAKER_STEREO
        | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT);

constexpr int SL_ANDROID_SPEAKER_5DOT1 = (SL_ANDROID_SPEAKER_QUAD
        | SL_SPEAKER_FRONT_CENTER  | SL_SPEAKER_LOW_FREQUENCY);

constexpr int SL_ANDROID_SPEAKER_7DOT1 = (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT
        | SL_SPEAKER_SIDE_RIGHT);

SLuint32 AudioOutputStreamOpenSLES::channelCountToChannelMask(int channelCount) const {
    SLuint32 channelMask = 0;

    switch (channelCount) {
        case  1:
            channelMask = SL_SPEAKER_FRONT_CENTER;
            break;

        case  2:
            channelMask = SL_ANDROID_SPEAKER_STEREO;
            break;

        case  4: // Quad
            channelMask = SL_ANDROID_SPEAKER_QUAD;
            break;

        case  6: // 5.1
            channelMask = SL_ANDROID_SPEAKER_5DOT1;
            break;

        case  8: // 7.1
            channelMask = SL_ANDROID_SPEAKER_7DOT1;
            break;

        default:
            channelMask = channelCountToChannelMaskDefault(channelCount);
            break;
    }
    return channelMask;
}

Result AudioOutputStreamOpenSLES::open() {
    logUnsupportedAttributes();

    SLAndroidConfigurationItf configItf = nullptr;


    if (getSdkVersion() < __ANDROID_API_L__ && mFormat == AudioFormat::Float){
        // TODO: Allow floating point format on API <21 using float->int16 converter
        return Result::ErrorInvalidFormat;
    }

    // If audio format is unspecified then choose a suitable default.
    // API 21+: FLOAT
    // API <21: INT16
    if (mFormat == AudioFormat::Unspecified){
        mFormat = (getSdkVersion() < __ANDROID_API_L__) ?
                  AudioFormat::I16 : AudioFormat::Float;
    }

    Result oboeResult = AudioStreamOpenSLES::open();
    if (Result::OK != oboeResult)  return oboeResult;

    SLresult result = OutputMixerOpenSL::getInstance().open();
    if (SL_RESULT_SUCCESS != result) {
        AudioStreamOpenSLES::close();
        return Result::ErrorInternal;
    }

    SLuint32 bitsPerSample = static_cast<SLuint32>(getBytesPerSample() * kBitsPerByte);

    // configure audio source
    mBufferQueueLength = calculateOptimalBufferQueueLength();
    SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
            SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,    // locatorType
            static_cast<SLuint32>(mBufferQueueLength)};   // numBuffers

    // Define the audio data format.
    SLDataFormat_PCM format_pcm = {
            SL_DATAFORMAT_PCM,       // formatType
            static_cast<SLuint32>(mChannelCount),           // numChannels
            static_cast<SLuint32>(mSampleRate * kMillisPerSecond),    // milliSamplesPerSec
            bitsPerSample,                      // mBitsPerSample
            bitsPerSample,                      // containerSize;
            channelCountToChannelMask(mChannelCount), // channelMask
            getDefaultByteOrder(),
    };

    SLDataSource audioSrc = {&loc_bufq, &format_pcm};

    /**
     * API 21 (Lollipop) introduced support for floating-point data representation and an extended
     * data format type: SLAndroidDataFormat_PCM_EX. If running on API 21+ use this newer format
     * type, creating it from our original format.
     */
    SLAndroidDataFormat_PCM_EX format_pcm_ex;
    if (getSdkVersion() >= __ANDROID_API_L__) {
        SLuint32 representation = OpenSLES_ConvertFormatToRepresentation(getFormat());
        // Fill in the format structure.
        format_pcm_ex = OpenSLES_createExtendedFormat(format_pcm, representation);
        // Use in place of the previous format.
        audioSrc.pFormat = &format_pcm_ex;
    }

    result = OutputMixerOpenSL::getInstance().createAudioPlayer(&mObjectInterface,
                                                                          &audioSrc);
    if (SL_RESULT_SUCCESS != result) {
        LOGE("createAudioPlayer() result:%s", getSLErrStr(result));
        goto error;
    }

    // Configure the stream.
    result = (*mObjectInterface)->GetInterface(mObjectInterface,
            EngineOpenSLES::getInstance().getIidAndroidConfiguration(),
            (void *)&configItf);
    if (SL_RESULT_SUCCESS != result) {
        LOGW("%s() GetInterface(SL_IID_ANDROIDCONFIGURATION) failed with %s",
             __func__, getSLErrStr(result));
    } else {
        result = configurePerformanceMode(configItf);
        if (SL_RESULT_SUCCESS != result) {
            goto error;
        }

        SLuint32 presetValue = OpenSLES_convertOutputUsage(getUsage());
        result = (*configItf)->SetConfiguration(configItf,
                                                SL_ANDROID_KEY_STREAM_TYPE,
                                                &presetValue,
                                                sizeof(presetValue));
        if (SL_RESULT_SUCCESS != result) {
            goto error;
        }
    }

    result = (*mObjectInterface)->Realize(mObjectInterface, SL_BOOLEAN_FALSE);
    if (SL_RESULT_SUCCESS != result) {
        LOGE("Realize player object result:%s", getSLErrStr(result));
        goto error;
    }

    result = (*mObjectInterface)->GetInterface(mObjectInterface,
                                               EngineOpenSLES::getInstance().getIidPlay(),
                                               &mPlayInterface);
    if (SL_RESULT_SUCCESS != result) {
        LOGE("GetInterface PLAY result:%s", getSLErrStr(result));
        goto error;
    }

    result = finishCommonOpen(configItf);
    if (SL_RESULT_SUCCESS != result) {
        goto error;
    }

    setState(StreamState::Open);
    return Result::OK;

error:
    close();  // Clean up various OpenSL objects and prevent resource leaks.
    return Result::ErrorInternal; // TODO convert error from SLES to OBOE
}

Result AudioOutputStreamOpenSLES::onAfterDestroy() {
    OutputMixerOpenSL::getInstance().close();
    return Result::OK;
}

Result AudioOutputStreamOpenSLES::close() {
    LOGD("AudioOutputStreamOpenSLES::%s()", __func__);
    std::lock_guard<std::mutex> lock(mLock);
    Result result = Result::OK;
    if (getState() == StreamState::Closed) {
        result = Result::ErrorClosed;
    } else {
        (void) requestPause_l();
        if (OboeGlobals::areWorkaroundsEnabled()) {
            sleepBeforeClose();
        }
        // invalidate any interfaces
        mPlayInterface = nullptr;
        result = AudioStreamOpenSLES::close_l();
    }
    return result;
}

Result AudioOutputStreamOpenSLES::setPlayState_l(SLuint32 newState) {
    LOGD("AudioOutputStreamOpenSLES::%s(%d) called", __func__, newState);
    Result result = Result::OK;

    if (mPlayInterface == nullptr){
        LOGE("AudioOutputStreamOpenSLES::%s() mPlayInterface is null", __func__);
        return Result::ErrorInvalidState;
    }

    SLresult slResult = (*mPlayInterface)->SetPlayState(mPlayInterface, newState);
    if (SL_RESULT_SUCCESS != slResult) {
        LOGW("AudioOutputStreamOpenSLES(): %s() returned %s", __func__, getSLErrStr(slResult));
        result = Result::ErrorInternal; // TODO convert slResult to Result::Error
    }
    return result;
}

Result AudioOutputStreamOpenSLES::requestStart() {
    LOGD("AudioOutputStreamOpenSLES::%s() called", __func__);

    mLock.lock();
    StreamState initialState = getState();
    switch (initialState) {
        case StreamState::Starting:
        case StreamState::Started:
            mLock.unlock();
            return Result::OK;
        case StreamState::Closed:
            mLock.unlock();
            return Result::ErrorClosed;
        default:
            break;
    }

    // We use a callback if the user requests one
    // OR if we have an internal callback to read the blocking IO buffer.
    setDataCallbackEnabled(true);

    setState(StreamState::Starting);
    closePerformanceHint();

    if (getBufferDepth(mSimpleBufferQueueInterface) == 0) {
        // Enqueue the first buffer if needed to start the streaming.
        // We may need to stop the current stream.
        bool shouldStopStream = processBufferCallback(mSimpleBufferQueueInterface);
        if (shouldStopStream) {
            LOGD("Stopping the current stream.");
            if (requestStop_l() != Result::OK) {
                LOGW("Failed to flush the stream. Error %s", convertToText(flush()));
            }
            setState(initialState);
            mLock.unlock();
            return Result::ErrorClosed;
        }
    }

    Result result = setPlayState_l(SL_PLAYSTATE_PLAYING);
    if (result == Result::OK) {
        setState(StreamState::Started);
        mLock.unlock();
    } else {
        setState(initialState);
        mLock.unlock();
    }
    return result;
}

Result AudioOutputStreamOpenSLES::requestPause() {
    LOGD("AudioOutputStreamOpenSLES::%s() called", __func__);
    std::lock_guard<std::mutex> lock(mLock);
    return requestPause_l();
}

// Call under mLock
Result AudioOutputStreamOpenSLES::requestPause_l() {
    StreamState initialState = getState();
    switch (initialState) {
        case StreamState::Pausing:
        case StreamState::Paused:
            return Result::OK;
        case StreamState::Uninitialized:
        case StreamState::Closed:
            return Result::ErrorClosed;
        default:
            break;
    }

    setState(StreamState::Pausing);
    Result result = setPlayState_l(SL_PLAYSTATE_PAUSED);
    if (result == Result::OK) {
        // Note that OpenSL ES does NOT reset its millisecond position when OUTPUT is paused.
        int64_t framesWritten = getFramesWritten();
        if (framesWritten >= 0) {
            setFramesRead(framesWritten);
        }
        setState(StreamState::Paused);
    } else {
        setState(initialState);
    }
    return result;
}

/**
 * Flush/clear the queue buffers
 */
Result AudioOutputStreamOpenSLES::requestFlush() {
    std::lock_guard<std::mutex> lock(mLock);
    return requestFlush_l();
}

Result AudioOutputStreamOpenSLES::requestFlush_l() {
    LOGD("AudioOutputStreamOpenSLES::%s() called", __func__);
    if (getState() == StreamState::Closed) {
        return Result::ErrorClosed;
    }

    Result result = Result::OK;
    if (mPlayInterface == nullptr || mSimpleBufferQueueInterface == nullptr) {
        result = Result::ErrorInvalidState;
    } else {
        SLresult slResult = (*mSimpleBufferQueueInterface)->Clear(mSimpleBufferQueueInterface);
        if (slResult != SL_RESULT_SUCCESS){
            LOGW("Failed to clear buffer queue. OpenSLES error: %s", getSLErrStr(slResult));
            result = Result::ErrorInternal;
        }
    }
    return result;
}

Result AudioOutputStreamOpenSLES::requestStop() {
    std::lock_guard<std::mutex> lock(mLock);
    return requestStop_l();
}

Result AudioOutputStreamOpenSLES::requestStop_l() {
    StreamState initialState = getState();
    LOGD("AudioOutputStreamOpenSLES::%s() called, initialState = %d", __func__, initialState);
    switch (initialState) {
        case StreamState::Stopping:
        case StreamState::Stopped:
            return Result::OK;
        case StreamState::Uninitialized:
        case StreamState::Closed:
            return Result::ErrorClosed;
        default:
            break;
    }

    setState(StreamState::Stopping);

    Result result = setPlayState_l(SL_PLAYSTATE_STOPPED);
    if (result == Result::OK) {

        // Also clear the buffer queue so the old data won't be played if the stream is restarted.
        // Call the _l function that expects to already be under a lock.
        if (requestFlush_l() != Result::OK) {
            LOGW("Failed to flush the stream. Error %s", convertToText(flush()));
        }

        mPositionMillis.reset32(); // OpenSL ES resets its millisecond position when stopped.
        int64_t framesWritten = getFramesWritten();
        if (framesWritten >= 0) {
            setFramesRead(framesWritten);
        }
        setState(StreamState::Stopped);
    } else {
        setState(initialState);
    }
    return result;
}

void AudioOutputStreamOpenSLES::setFramesRead(int64_t framesRead) {
    int64_t millisWritten = framesRead * kMillisPerSecond / getSampleRate();
    mPositionMillis.set(millisWritten);
}

void AudioOutputStreamOpenSLES::updateFramesRead() {
    if (usingFIFO()) {
        AudioStreamBuffered::updateFramesRead();
    } else {
        mFramesRead = getFramesProcessedByServer();
    }
}

Result AudioOutputStreamOpenSLES::updateServiceFrameCounter() {
    Result result = Result::OK;
    // Avoid deadlock if another thread is trying to stop or close this stream
    // and this is being called from a callback.
    if (mLock.try_lock()) {

        if (mPlayInterface == nullptr) {
            mLock.unlock();
            return Result::ErrorNull;
        }
        SLmillisecond msec = 0;
        SLresult slResult = (*mPlayInterface)->GetPosition(mPlayInterface, &msec);
        if (SL_RESULT_SUCCESS != slResult) {
            LOGW("%s(): GetPosition() returned %s", __func__, getSLErrStr(slResult));
            // set result based on SLresult
            result = Result::ErrorInternal;
        } else {
            mPositionMillis.update32(msec);
        }
        mLock.unlock();
    }
    return result;
}
