/*
 * Copyright (C) 2017-2018 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. AND ITS CONTRIBUTORS ``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 ITS 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 "AVAudioSessionCaptureDeviceManager.h"

#if ENABLE(MEDIA_STREAM) && PLATFORM(IOS_FAMILY)

#import "AVAudioSessionCaptureDevice.h"
#import "Logging.h"
#import "RealtimeMediaSourceCenter.h"
#import <AVFoundation/AVAudioSession.h>
#import <pal/spi/cocoa/AVFoundationSPI.h>
#import <wtf/Assertions.h>
#import <wtf/BlockPtr.h>
#import <wtf/MainThread.h>
#import <wtf/Vector.h>

#import <pal/cocoa/AVFoundationSoftLink.h>

@interface WebAVAudioSessionAvailableInputsListener : NSObject {
    WebCore::AVAudioSessionCaptureDeviceManager* _callback;
}
@end

@implementation WebAVAudioSessionAvailableInputsListener
- (id)initWithCallback:(WebCore::AVAudioSessionCaptureDeviceManager *)callback audioSession:(AVAudioSession *)session
{
    self = [super init];
    if (!self)
        return nil;

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(routeDidChange:) name:PAL::get_AVFoundation_AVAudioSessionRouteChangeNotification() object:session];

    _callback = callback;

    return self;
}

- (void)invalidate
{
    _callback = nullptr;
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)routeDidChange:(NSNotification *)notification
{
    if (!_callback)
        return;

    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self)]() mutable {
        if (auto* callback = protectedSelf->_callback)
            callback->scheduleUpdateCaptureDevices();
    });
}

@end

namespace WebCore {

AVAudioSessionCaptureDeviceManager& AVAudioSessionCaptureDeviceManager::singleton()
{
    static NeverDestroyed<AVAudioSessionCaptureDeviceManager> manager;
    return manager;
}

AVAudioSessionCaptureDeviceManager::AVAudioSessionCaptureDeviceManager()
    : m_dispatchQueue(WorkQueue::create("com.apple.WebKit.AVAudioSessionCaptureDeviceManager"))
{
    m_dispatchQueue->dispatch([this] {
        createAudioSession();
    });
}

void AVAudioSessionCaptureDeviceManager::createAudioSession()
{
#if !PLATFORM(MACCATALYST)
    m_audioSession = adoptNS([[PAL::getAVAudioSessionClass() alloc] initAuxiliarySession]);
#else
    // FIXME: Figure out if this is correct for Catalyst, where auxiliary session isn't available.
    m_audioSession = [PAL::getAVAudioSessionClass() sharedInstance];
#endif

    NSError *error = nil;
    auto options = AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionMixWithOthers;
    [m_audioSession setCategory:AVAudioSessionCategoryPlayAndRecord mode:AVAudioSessionModeDefault options:options error:&error];
    RELEASE_LOG_ERROR_IF(error, WebRTC, "Failed to set audio session category with error: %@.", error.localizedDescription);
}

AVAudioSessionCaptureDeviceManager::~AVAudioSessionCaptureDeviceManager()
{
    [m_listener invalidate];
    m_listener = nullptr;
}

const Vector<CaptureDevice>& AVAudioSessionCaptureDeviceManager::captureDevices()
{
    if (!m_devices)
        refreshAudioCaptureDevices();
    return m_devices.value();
}

std::optional<CaptureDevice> AVAudioSessionCaptureDeviceManager::captureDeviceWithPersistentID(CaptureDevice::DeviceType type, const String& deviceID)
{
    ASSERT_UNUSED(type, type == CaptureDevice::DeviceType::Microphone);
    for (auto& device : captureDevices()) {
        if (device.persistentId() == deviceID)
            return device;
    }
    return std::nullopt;
}

std::optional<AVAudioSessionCaptureDevice> AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID(const String& deviceID)
{
    if (!m_audioSessionCaptureDevices)
        refreshAudioCaptureDevices();

    for (auto& device : *m_audioSessionCaptureDevices) {
        if (device.persistentId() == deviceID)
            return device;
    }
    return std::nullopt;
}

void AVAudioSessionCaptureDeviceManager::setPreferredAudioSessionDeviceUID(const String& deviceUID)
{
    if (setPreferredAudioSessionDeviceUIDInternal(deviceUID))
        m_preferredAudioDeviceUID = deviceUID;
}

void AVAudioSessionCaptureDeviceManager::configurePreferredAudioCaptureDevice()
{
    ASSERT(!m_preferredAudioDeviceUID.isEmpty());
    if (!m_preferredAudioDeviceUID.isEmpty())
        setPreferredAudioSessionDeviceUIDInternal(m_preferredAudioDeviceUID);
}

bool AVAudioSessionCaptureDeviceManager::setPreferredAudioSessionDeviceUIDInternal(const String& deviceUID)
{
    AVAudioSessionPortDescription *preferredPort = nil;
    NSString *nsDeviceUID = deviceUID;
    for (AVAudioSessionPortDescription *portDescription in [m_audioSession availableInputs]) {
        if ([portDescription.UID isEqualToString:nsDeviceUID]) {
            preferredPort = portDescription;
            break;
        }
    }

    if (!preferredPort) {
        RELEASE_LOG_ERROR(WebRTC, "failed to find preferred input '%{public}s'", deviceUID.ascii().data());
        return false;
    }

    NSError *error = nil;
    if (![[PAL::getAVAudioSessionClass() sharedInstance] setPreferredInput:preferredPort error:&error]) {
        RELEASE_LOG_ERROR(WebRTC, "failed to set preferred input to '%{public}s' with error: %@", deviceUID.ascii().data(), error.localizedDescription);
        return false;
    }

    return true;
}

void AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices()
{
    computeCaptureDevices([] { });
}

void AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
{
    if (m_audioSessionState == AudioSessionState::Inactive) {
        m_audioSessionState = AudioSessionState::Active;

        m_dispatchQueue->dispatchSync([this] {
            activateAudioSession();
        });
    }

    Vector<AVAudioSessionCaptureDevice> newAudioDevices;
    m_dispatchQueue->dispatchSync([&] {
        newAudioDevices = retrieveAudioSessionCaptureDevices();
    });
    setAudioCaptureDevices(WTFMove(newAudioDevices).isolatedCopy());
}

void AVAudioSessionCaptureDeviceManager::computeCaptureDevices(CompletionHandler<void()>&& completion)
{
    if (m_audioSessionState == AudioSessionState::Inactive) {
        m_audioSessionState = AudioSessionState::Active;

        m_dispatchQueue->dispatch([this] {
            activateAudioSession();
        });
    }

    m_dispatchQueue->dispatch([this, completion = WTFMove(completion)] () mutable {
        auto newAudioDevices = retrieveAudioSessionCaptureDevices();
        callOnWebThreadOrDispatchAsyncOnMainThread(makeBlockPtr([this, completion = WTFMove(completion), newAudioDevices = WTFMove(newAudioDevices).isolatedCopy()] () mutable {
            setAudioCaptureDevices(WTFMove(newAudioDevices));
            completion();
        }).get());
    });
}

void AVAudioSessionCaptureDeviceManager::activateAudioSession()
{
    if (!m_listener)
        m_listener = adoptNS([[WebAVAudioSessionAvailableInputsListener alloc] initWithCallback:this audioSession:m_audioSession.get()]);

    NSError *error = nil;
    [m_audioSession setActive:YES withOptions:0 error:&error];
    if (error)
        RELEASE_LOG_ERROR(WebRTC, "Failed to activate audio session with error: %@.", error.localizedDescription);
}

Vector<AVAudioSessionCaptureDevice> AVAudioSessionCaptureDeviceManager::retrieveAudioSessionCaptureDevices() const
{
    auto *defaultInput = [m_audioSession currentRoute].inputs.firstObject;
    if (!defaultInput) {
        RELEASE_LOG_INFO(WebRTC, "AVAudioSessionCaptureDeviceManager using previous default input");
        defaultInput = m_lastDefaultMicrophone.get();
    } else
        m_lastDefaultMicrophone = defaultInput;

    auto availableInputs = [m_audioSession availableInputs];

    Vector<AVAudioSessionCaptureDevice> newAudioDevices;
    newAudioDevices.reserveInitialCapacity(availableInputs.count);
    for (AVAudioSessionPortDescription *portDescription in availableInputs)
        newAudioDevices.uncheckedAppend(AVAudioSessionCaptureDevice::create(portDescription, defaultInput));

    return newAudioDevices;
}

void AVAudioSessionCaptureDeviceManager::setAudioCaptureDevices(Vector<AVAudioSessionCaptureDevice>&& newAudioDevices)
{
    bool firstTime = !m_devices;
    bool deviceListChanged = newAudioDevices.size() != m_devices->size();
    bool defaultDeviceChanged = false;
    if (!deviceListChanged && !firstTime) {
        for (auto& newState : newAudioDevices) {

            std::optional<CaptureDevice> oldState;
            for (const auto& device : m_devices.value()) {
                if (device.type() == newState.type() && device.persistentId() == newState.persistentId()) {
                    oldState = device;
                    break;
                }
            }

            if (!oldState.has_value()) {
                deviceListChanged = true;
                break;
            }
            if (newState.isDefault() != oldState.value().isDefault())
                defaultDeviceChanged  = true;

            if (newState.enabled() != oldState.value().enabled()) {
                deviceListChanged = true;
                break;
            }
        }
    }

    if (!deviceListChanged && !firstTime && !defaultDeviceChanged)
        return;

    auto newDevices = copyToVectorOf<CaptureDevice>(newAudioDevices);
    m_audioSessionCaptureDevices = WTFMove(newAudioDevices);
    std::sort(newDevices.begin(), newDevices.end(), [] (auto& first, auto& second) -> bool {
        return first.isDefault() && !second.isDefault();
    });
    m_devices = WTFMove(newDevices);

    if (deviceListChanged && !firstTime)
        deviceChanged();
}

void AVAudioSessionCaptureDeviceManager::enableAllDevicesQuery()
{
    if (m_audioSessionState != AudioSessionState::NotNeeded)
        return;

    m_audioSessionState = AudioSessionState::Inactive;
    refreshAudioCaptureDevices();
}

void AVAudioSessionCaptureDeviceManager::disableAllDevicesQuery()
{
    if (m_audioSessionState == AudioSessionState::NotNeeded)
        return;

    if (m_audioSessionState == AudioSessionState::Active) {
        m_dispatchQueue->dispatch([this] {
            if (m_audioSessionState != AudioSessionState::NotNeeded)
                return;
            NSError *error = nil;
            [m_audioSession setActive:NO withOptions:0 error:&error];
            if (error)
                RELEASE_LOG_ERROR(WebRTC, "Failed to disactivate audio session with error: %@.", error.localizedDescription);
        });
    }

    m_audioSessionState = AudioSessionState::NotNeeded;
}

} // namespace WebCore

#endif // ENABLE(MEDIA_STREAM) && PLATFORM(IOS_FAMILY)
