/*
 * Copyright (C) 2016-2022 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


#import "config.h"
#import "MockAudioSharedUnit.h"

#if ENABLE(MEDIA_STREAM)
#import "AudioSampleBufferList.h"
#import "AudioSession.h"
#import "BaseAudioSharedUnit.h"
#import "CAAudioStreamDescription.h"
#import "CoreAudioCaptureSource.h"
#import "MediaConstraints.h"
#import "MediaSampleAVFObjC.h"
#import "MockRealtimeMediaSourceCenter.h"
#import "NotImplemented.h"
#import "RealtimeMediaSourceSettings.h"
#import "WebAudioBufferList.h"
#import "WebAudioSourceProviderCocoa.h"
#import <AVFoundation/AVAudioBuffer.h>
#import <AudioToolbox/AudioConverter.h>
#import <CoreAudio/CoreAudioTypes.h>
#include <wtf/RunLoop.h>
#include <wtf/Vector.h>
#include <wtf/WorkQueue.h>

#import <pal/cf/AudioToolboxSoftLink.h>
#import <pal/cf/CoreMediaSoftLink.h>

namespace WebCore {

static inline size_t alignTo16Bytes(size_t size)
{
    return (size + 15) & ~15;
}

static const double Tau = 2 * M_PI;
static const double BipBopDuration = 0.07;
static const double BipBopVolume = 0.5;
static const double BipFrequency = 1500;
static const double BopFrequency = 500;
static const double HumFrequency = 150;
static const double HumVolume = 0.1;
static const double NoiseFrequency = 3000;
static const double NoiseVolume = 0.05;

template <typename AudioSampleType>
static void writeHum(float amplitude, float frequency, float sampleRate, AudioSampleType *p, uint64_t count)
{
    float humPeriod = sampleRate / frequency;
    for (uint64_t i = 0; i < count; ++i)
        *p++ = amplitude * sin(i * Tau / humPeriod);
}

template <typename AudioSampleType>
static void addHum(float amplitude, float frequency, float sampleRate, uint64_t start, AudioSampleType *p, uint64_t count)
{
    float humPeriod = sampleRate / frequency;
    for (uint64_t i = start, end = start + count; i < end; ++i) {
        AudioSampleType a = amplitude * sin(i * Tau / humPeriod);
        a += *p;
        *p++ = a;
    }
}

CaptureSourceOrError MockRealtimeAudioSource::create(String&& deviceID, AtomString&& name, String&& hashSalt, const MediaConstraints* constraints, PageIdentifier pageIdentifier)
{
    auto device = MockRealtimeMediaSourceCenter::mockDeviceWithPersistentID(deviceID);
    ASSERT(device);
    if (!device)
        return { "No mock microphone device"_s };

    MockAudioSharedUnit::singleton().setCaptureDevice(String { deviceID }, 0);
    return CoreAudioCaptureSource::createForTesting(WTFMove(deviceID), WTFMove(name), WTFMove(hashSalt), constraints, MockAudioSharedUnit::singleton(), pageIdentifier);
}

class MockAudioSharedInternalUnitState : public ThreadSafeRefCounted<MockAudioSharedInternalUnitState> {
public:
    static Ref<MockAudioSharedInternalUnitState> create() { return adoptRef(*new MockAudioSharedInternalUnitState()); }

    bool isProducingData() const { return m_isProducingData; }
    void setIsProducingData(bool value) { m_isProducingData = value; }

private:
    bool m_isProducingData { false };
};

class MockAudioSharedInternalUnit :  public CoreAudioSharedUnit::InternalUnit {
    WTF_MAKE_FAST_ALLOCATED;
public:
    MockAudioSharedInternalUnit();
    ~MockAudioSharedInternalUnit();

private:
    OSStatus initialize() final;
    OSStatus uninitialize() final;
    OSStatus start() final;
    OSStatus stop() final;
    OSStatus set(AudioUnitPropertyID, AudioUnitScope, AudioUnitElement, const void*, UInt32) final;
    OSStatus get(AudioUnitPropertyID, AudioUnitScope, AudioUnitElement, void*, UInt32*) final;
    OSStatus render(AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32, UInt32, AudioBufferList*) final;
    OSStatus defaultInputDevice(uint32_t*) final;
    OSStatus defaultOutputDevice(uint32_t*) final;
    void delaySamples(Seconds) final;

    int sampleRate() const { return m_streamFormat.mSampleRate; }
    void tick();

    void generateSampleBuffers(MonotonicTime);
    void emitSampleBuffers(uint32_t frameCount);
    void reconfigure();

    static Seconds renderInterval() { return 20_ms; }

    std::unique_ptr<WebAudioBufferList> m_audioBufferList;

    uint32_t m_maximiumFrameCount;
    uint64_t m_samplesEmitted { 0 };
    uint64_t m_samplesRendered { 0 };

    RetainPtr<CMFormatDescriptionRef> m_formatDescription;
    AudioStreamBasicDescription m_outputStreamFormat;
    AudioStreamBasicDescription m_streamFormat;

    Vector<float> m_bipBopBuffer;
    bool m_hasAudioUnit { false };
    Ref<MockAudioSharedInternalUnitState> m_internalState;
    bool m_enableEchoCancellation { true };
    RunLoop::Timer<MockAudioSharedInternalUnit> m_timer;
    MonotonicTime m_lastRenderTime { MonotonicTime::nan() };
    MonotonicTime m_delayUntil;

    Ref<WorkQueue> m_workQueue;
    unsigned m_channelCount { 2 };
    
    AURenderCallbackStruct m_microphoneCallback;
    AURenderCallbackStruct m_speakerCallback;
};

CoreAudioSharedUnit& MockAudioSharedUnit::singleton()
{
    static NeverDestroyed<CoreAudioSharedUnit> unit;
    static std::once_flag onceFlag;
    std::call_once(onceFlag, [&] () {
        unit->setSampleRateRange(CapabilityValueOrRange(44100, 48000));
        unit->setInternalUnitCreationCallback([] {
            UniqueRef<CoreAudioSharedUnit::InternalUnit> result = makeUniqueRef<MockAudioSharedInternalUnit>();
            return result;
        });
        unit->setInternalUnitGetSampleRateCallback([] { return 44100; });
    });
    return unit;
}

static AudioStreamBasicDescription createAudioFormat(Float64 sampleRate, UInt32 channelCount)
{
    AudioStreamBasicDescription format;
    const int bytesPerFloat = sizeof(Float32);
    const int bitsPerByte = 8;
    const bool isFloat = true;
    const bool isBigEndian = false;
    const bool isNonInterleaved = true;
    FillOutASBDForLPCM(format, sampleRate, channelCount, bitsPerByte * bytesPerFloat, bitsPerByte * bytesPerFloat, isFloat, isBigEndian, isNonInterleaved);
    return format;
}

MockAudioSharedInternalUnit::MockAudioSharedInternalUnit()
    : m_internalState(MockAudioSharedInternalUnitState::create())
    , m_timer(RunLoop::current(), [this] { this->start(); })
    , m_workQueue(WorkQueue::create("MockAudioSharedInternalUnit Capture Queue", WorkQueue::QOS::UserInteractive))
{
    m_streamFormat = m_outputStreamFormat = createAudioFormat(44100, 2);
}

MockAudioSharedInternalUnit::~MockAudioSharedInternalUnit()
{
    ASSERT(!m_internalState->isProducingData());
}

OSStatus MockAudioSharedInternalUnit::initialize()
{
    ASSERT(m_outputStreamFormat.mSampleRate == m_streamFormat.mSampleRate);
    if (m_outputStreamFormat.mSampleRate != m_streamFormat.mSampleRate)
        return -1;

    return 0;
}

OSStatus MockAudioSharedInternalUnit::start()
{
    if (!m_hasAudioUnit)
        m_hasAudioUnit = true;

    m_lastRenderTime = MonotonicTime::now();

    m_internalState->setIsProducingData(true);
    m_workQueue->dispatch([this, renderTime = m_lastRenderTime] {
        generateSampleBuffers(renderTime);
    });
    return 0;
}

OSStatus MockAudioSharedInternalUnit::stop()
{
    m_internalState->setIsProducingData(false);
    if (m_hasAudioUnit)
        m_lastRenderTime = MonotonicTime::nan();

    m_workQueue->dispatchSync([] { });

    return 0;
}

OSStatus MockAudioSharedInternalUnit::uninitialize()
{
    ASSERT(!m_internalState->isProducingData());
    return 0;
}

void MockAudioSharedInternalUnit::delaySamples(Seconds delta)
{
    stop();
    m_timer.startOneShot(delta);
}

void MockAudioSharedInternalUnit::reconfigure()
{
    ASSERT(!isMainThread());

    auto rate = sampleRate();
    ASSERT(rate);

    m_maximiumFrameCount = WTF::roundUpToPowerOfTwo(renderInterval().seconds() * rate * 2);
    ASSERT(m_maximiumFrameCount);

    m_audioBufferList = makeUnique<WebAudioBufferList>(m_streamFormat, m_maximiumFrameCount);

    CMFormatDescriptionRef formatDescription;
    PAL::CMAudioFormatDescriptionCreate(NULL, &m_streamFormat, 0, NULL, 0, NULL, NULL, &formatDescription);
    m_formatDescription = adoptCF(formatDescription);

    size_t sampleCount = 2 * rate;
    m_bipBopBuffer.resize(sampleCount);
    m_bipBopBuffer.fill(0);

    size_t bipBopSampleCount = ceil(BipBopDuration * rate);
    size_t bipStart = 0;
    size_t bopStart = rate;

    addHum(BipBopVolume, BipFrequency, rate, 0, m_bipBopBuffer.data() + bipStart, bipBopSampleCount);
    addHum(BipBopVolume, BopFrequency, rate, 0, m_bipBopBuffer.data() + bopStart, bipBopSampleCount);
    if (!m_enableEchoCancellation)
        addHum(NoiseVolume, NoiseFrequency, rate, 0, m_bipBopBuffer.data(), sampleCount);
}

void MockAudioSharedInternalUnit::emitSampleBuffers(uint32_t frameCount)
{
    ASSERT(!isMainThread());
    ASSERT(m_formatDescription);

    CMTime startTime = PAL::CMTimeMake(m_samplesEmitted, sampleRate());
    auto sampleTime = PAL::CMTimeGetSeconds(startTime);
    m_samplesEmitted += frameCount;

    auto* bufferList = m_audioBufferList->list();
    AudioUnitRenderActionFlags ioActionFlags = 0;
    
    AudioTimeStamp timeStamp;
    memset(&timeStamp, 0, sizeof(AudioTimeStamp));
    timeStamp.mSampleTime = sampleTime;
    timeStamp.mHostTime = static_cast<UInt64>(sampleTime);
    if (m_microphoneCallback.inputProc)
        m_microphoneCallback.inputProc(m_microphoneCallback.inputProcRefCon, &ioActionFlags, &timeStamp, 1, frameCount, bufferList);

    ioActionFlags = 0;
    if (m_speakerCallback.inputProc)
        m_speakerCallback.inputProc(m_speakerCallback.inputProcRefCon, &ioActionFlags, &timeStamp, 1, frameCount, bufferList);
}

void MockAudioSharedInternalUnit::generateSampleBuffers(MonotonicTime renderTime)
{
    auto delta = renderInterval();
    auto currentTime = MonotonicTime::now();
    auto nextRenderTime = renderTime + delta;
    Seconds nextRenderDelay = nextRenderTime.secondsSinceEpoch() - currentTime.secondsSinceEpoch();
    if (nextRenderDelay.seconds() < 0) {
        nextRenderTime = currentTime;
        nextRenderDelay = 0_s;
    }

    m_workQueue->dispatchAfter(nextRenderDelay, [this, nextRenderTime, state = m_internalState] {
        if (state->isProducingData())
            generateSampleBuffers(nextRenderTime);
    });

    if (!m_audioBufferList || !m_bipBopBuffer.size())
        reconfigure();

    uint32_t totalFrameCount = alignTo16Bytes(delta.seconds() * sampleRate());
    uint32_t frameCount = std::min(totalFrameCount, static_cast<uint32_t>(AudioSession::sharedSession().bufferSize()));

    while (frameCount) {
        uint32_t bipBopStart = m_samplesRendered % m_bipBopBuffer.size();
        uint32_t bipBopRemain = m_bipBopBuffer.size() - bipBopStart;
        uint32_t bipBopCount = std::min(frameCount, bipBopRemain);
        for (auto& audioBuffer : m_audioBufferList->buffers()) {
            audioBuffer.mDataByteSize = frameCount * m_streamFormat.mBytesPerFrame;
            memcpy(audioBuffer.mData, &m_bipBopBuffer[bipBopStart], sizeof(Float32) * bipBopCount);
            addHum(HumVolume, HumFrequency, sampleRate(), m_samplesRendered, static_cast<float*>(audioBuffer.mData), bipBopCount);
        }
        emitSampleBuffers(bipBopCount);
        m_samplesRendered += bipBopCount;
        totalFrameCount -= bipBopCount;
        frameCount = std::min(totalFrameCount, static_cast<uint32_t>(AudioSession::sharedSession().bufferSize()));
    }
}

OSStatus MockAudioSharedInternalUnit::render(AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32, UInt32 frameCount, AudioBufferList* buffer)
{
    auto* sourceBuffer = m_audioBufferList->list();
    if (buffer->mNumberBuffers > sourceBuffer->mNumberBuffers)
        return kAudio_ParamError;

    auto copySize = frameCount * m_streamFormat.mBytesPerPacket;
    for (uint32_t i = 0; i < buffer->mNumberBuffers; i++) {
        ASSERT(copySize <= sourceBuffer->mBuffers[i].mDataByteSize);
        if (copySize > buffer->mBuffers[i].mDataByteSize)
            return kAudio_ParamError;

        auto* source = static_cast<uint8_t*>(sourceBuffer->mBuffers[i].mData);
        auto* destination = static_cast<uint8_t*>(buffer->mBuffers[i].mData);
        memcpy(destination, source, copySize);
    }

    return 0;
}

OSStatus MockAudioSharedInternalUnit::set(AudioUnitPropertyID property, AudioUnitScope scope, AudioUnitElement, const void* value, UInt32)
{
    if (property == kAudioUnitProperty_StreamFormat) {
        auto& typedValue = *static_cast<const AudioStreamBasicDescription*>(value);
        if (scope == kAudioUnitScope_Input)
            m_streamFormat = typedValue;
        else
            m_outputStreamFormat = typedValue;
        return 0;
    }
    if (property == kAUVoiceIOProperty_VoiceProcessingEnableAGC) {
        m_enableEchoCancellation = !!*static_cast<const uint32_t*>(value);
        return 0;
    }
    if (property == kAudioOutputUnitProperty_SetInputCallback) {
        m_microphoneCallback = *static_cast<const AURenderCallbackStruct*>(value);
        return 0;
    }
    if (property == kAudioUnitProperty_SetRenderCallback) {
        m_speakerCallback = *static_cast<const AURenderCallbackStruct*>(value);
        return 0;
    }
    if (property == kAudioOutputUnitProperty_CurrentDevice) {
        ASSERT(!*static_cast<const uint32_t*>(value));
        if (auto device = MockRealtimeMediaSourceCenter::mockDeviceWithPersistentID(MockAudioSharedUnit::singleton().persistentIDForTesting()))
            m_streamFormat.mSampleRate = m_outputStreamFormat.mSampleRate = std::get<MockMicrophoneProperties>(device->properties).defaultSampleRate;
        return 0;
    }
    
    return 0;
}

OSStatus MockAudioSharedInternalUnit::get(AudioUnitPropertyID property, AudioUnitScope scope, AudioUnitElement, void* value, UInt32* valueSize)
{
    if (property == kAudioUnitProperty_StreamFormat) {
        auto& typedValue = *static_cast<AudioStreamBasicDescription*>(value);
        if (scope == kAudioUnitScope_Input)
            typedValue = m_streamFormat;
        else
            typedValue = m_outputStreamFormat;
        *valueSize = sizeof(AudioStreamBasicDescription);
        return 0;
    }

    return 0;
}

OSStatus MockAudioSharedInternalUnit::defaultInputDevice(uint32_t* device)
{
    *device = 0;
    return 0;
}

OSStatus MockAudioSharedInternalUnit::defaultOutputDevice(uint32_t* device)
{
    *device = 0;
    return 0;
}

} // namespace WebCore

#endif // ENABLE(MEDIA_STREAM)
