/*
 * Copyright (C) 2022 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 <algorithm>
#include <chrono>

#include <Utils.h>
#include <aidl/android/media/audio/common/AudioInputFlags.h>
#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>

#include "ModuleConfig.h"

using namespace android;
using namespace std::chrono_literals;

using aidl::android::hardware::audio::common::isBitPositionFlagSet;
using aidl::android::hardware::audio::core::IModule;
using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioEncapsulationMode;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioProfile;
using aidl::android::media::audio::common::AudioUsage;
using aidl::android::media::audio::common::Int;

// static
std::optional<AudioOffloadInfo> ModuleConfig::generateOffloadInfoIfNeeded(
        const AudioPortConfig& portConfig) {
    if (portConfig.flags.has_value() &&
        portConfig.flags.value().getTag() == AudioIoFlags::Tag::output &&
        isBitPositionFlagSet(portConfig.flags.value().get<AudioIoFlags::Tag::output>(),
                             AudioOutputFlags::COMPRESS_OFFLOAD)) {
        AudioOffloadInfo offloadInfo;
        offloadInfo.base.sampleRate = portConfig.sampleRate.value().value;
        offloadInfo.base.channelMask = portConfig.channelMask.value();
        offloadInfo.base.format = portConfig.format.value();
        offloadInfo.bitRatePerSecond = 256000;                             // Arbitrary value.
        offloadInfo.durationUs = std::chrono::microseconds(1min).count();  // Arbitrary value.
        offloadInfo.usage = AudioUsage::MEDIA;
        offloadInfo.encapsulationMode = AudioEncapsulationMode::NONE;
        return offloadInfo;
    }
    return {};
}

// static
std::vector<aidl::android::media::audio::common::AudioPort> ModuleConfig::getBuiltInMicPorts(
        const std::vector<aidl::android::media::audio::common::AudioPort>& ports) {
    std::vector<AudioPort> result;
    std::copy_if(ports.begin(), ports.end(), std::back_inserter(result), [](const auto& port) {
        const auto type = port.ext.template get<AudioPortExt::Tag::device>().device.type;
        return type.connection.empty() && (type.type == AudioDeviceType::IN_MICROPHONE ||
                                           type.type == AudioDeviceType::IN_MICROPHONE_BACK);
    });
    return result;
}

template <typename T>
auto findById(const std::vector<T>& v, int32_t id) {
    return std::find_if(v.begin(), v.end(), [&](const auto& p) { return p.id == id; });
}

ModuleConfig::ModuleConfig(IModule* module) {
    mStatus = module->getAudioPorts(&mPorts);
    if (!mStatus.isOk()) return;
    for (const auto& port : mPorts) {
        if (port.ext.getTag() != AudioPortExt::Tag::device) continue;
        const auto& devicePort = port.ext.get<AudioPortExt::Tag::device>();
        if (devicePort.device.type.connection.empty()) {
            const bool isInput = port.flags.getTag() == AudioIoFlags::Tag::input;
            // Permanently attached device.
            if (isInput) {
                mAttachedSourceDevicePorts.insert(port.id);
            } else {
                mAttachedSinkDevicePorts.insert(port.id);
            }
        } else if (port.profiles.empty()) {
            mExternalDevicePorts.insert(port.id);
        }
    }
    if (!mStatus.isOk()) return;
    mStatus = module->getAudioRoutes(&mRoutes);
    if (!mStatus.isOk()) return;
    mStatus = module->getAudioPortConfigs(&mInitialConfigs);
}

std::vector<AudioPort> ModuleConfig::getAttachedDevicePorts() const {
    std::vector<AudioPort> result;
    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
        return mAttachedSinkDevicePorts.count(port.id) != 0 ||
               mAttachedSourceDevicePorts.count(port.id) != 0;
    });
    return result;
}

std::vector<AudioPort> ModuleConfig::getExternalDevicePorts() const {
    std::vector<AudioPort> result;
    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result),
                 [&](const auto& port) { return mExternalDevicePorts.count(port.id) != 0; });
    return result;
}

std::vector<AudioPort> ModuleConfig::getInputMixPorts(bool attachedOnly) const {
    std::vector<AudioPort> result;
    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
        return port.ext.getTag() == AudioPortExt::Tag::mix &&
               port.flags.getTag() == AudioIoFlags::Tag::input &&
               (!attachedOnly || !getAttachedSourceDevicesPortsForMixPort(port).empty());
    });
    return result;
}

std::vector<AudioPort> ModuleConfig::getOutputMixPorts(bool attachedOnly) const {
    std::vector<AudioPort> result;
    std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
        return port.ext.getTag() == AudioPortExt::Tag::mix &&
               port.flags.getTag() == AudioIoFlags::Tag::output &&
               (!attachedOnly || !getAttachedSinkDevicesPortsForMixPort(port).empty());
    });
    return result;
}

std::vector<AudioPort> ModuleConfig::getNonBlockingMixPorts(bool attachedOnly,
                                                            bool singlePort) const {
    return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
        return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
                                    AudioOutputFlags::NON_BLOCKING);
    });
}

std::vector<AudioPort> ModuleConfig::getOffloadMixPorts(bool attachedOnly, bool singlePort) const {
    return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
        return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
                                    AudioOutputFlags::COMPRESS_OFFLOAD);
    });
}

std::vector<AudioPort> ModuleConfig::getPrimaryMixPorts(bool attachedOnly, bool singlePort) const {
    return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
        return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
                                    AudioOutputFlags::PRIMARY);
    });
}

std::vector<AudioPort> ModuleConfig::getMmapOutMixPorts(bool attachedOnly, bool singlePort) const {
    return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
        return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
                                    AudioOutputFlags::MMAP_NOIRQ);
    });
}

std::vector<AudioPort> ModuleConfig::getMmapInMixPorts(bool attachedOnly, bool singlePort) const {
    return findMixPorts(true /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
        return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::input>(),
                                    AudioInputFlags::MMAP_NOIRQ);
    });
}

std::vector<AudioPort> ModuleConfig::getAttachedDevicesPortsForMixPort(
        bool isInput, const AudioPortConfig& mixPortConfig) const {
    const auto mixPortIt = findById<AudioPort>(mPorts, mixPortConfig.portId);
    if (mixPortIt != mPorts.end()) {
        return getAttachedDevicesPortsForMixPort(isInput, *mixPortIt);
    }
    return {};
}

std::vector<AudioPort> ModuleConfig::getAttachedSinkDevicesPortsForMixPort(
        const AudioPort& mixPort) const {
    std::vector<AudioPort> result;
    for (const auto& route : mRoutes) {
        if (mAttachedSinkDevicePorts.count(route.sinkPortId) != 0 &&
            std::find(route.sourcePortIds.begin(), route.sourcePortIds.end(), mixPort.id) !=
                    route.sourcePortIds.end()) {
            const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
            if (devicePortIt != mPorts.end()) result.push_back(*devicePortIt);
        }
    }
    return result;
}

std::vector<AudioPort> ModuleConfig::getAttachedSourceDevicesPortsForMixPort(
        const AudioPort& mixPort) const {
    std::vector<AudioPort> result;
    for (const auto& route : mRoutes) {
        if (route.sinkPortId == mixPort.id) {
            for (const auto srcId : route.sourcePortIds) {
                if (mAttachedSourceDevicePorts.count(srcId) != 0) {
                    const auto devicePortIt = findById<AudioPort>(mPorts, srcId);
                    if (devicePortIt != mPorts.end()) result.push_back(*devicePortIt);
                }
            }
        }
    }
    return result;
}

std::optional<AudioPort> ModuleConfig::getSourceMixPortForAttachedDevice() const {
    for (const auto& route : mRoutes) {
        if (mAttachedSinkDevicePorts.count(route.sinkPortId) != 0) {
            const auto mixPortIt = findById<AudioPort>(mPorts, route.sourcePortIds[0]);
            if (mixPortIt != mPorts.end()) return *mixPortIt;
        }
    }
    return {};
}

std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair(
        bool isInput) const {
    const auto mixPorts = getMixPorts(isInput, false /*attachedOnly*/);
    std::set<std::pair<int32_t, int32_t>> allowedRoutes;
    for (const auto& route : mRoutes) {
        for (const auto srcPortId : route.sourcePortIds) {
            allowedRoutes.emplace(std::make_pair(srcPortId, route.sinkPortId));
        }
    }
    auto make_pair = [isInput](auto& device, auto& mix) {
        return isInput ? std::make_pair(device, mix) : std::make_pair(mix, device);
    };
    for (const auto portId : isInput ? mAttachedSourceDevicePorts : mAttachedSinkDevicePorts) {
        const auto devicePortIt = findById<AudioPort>(mPorts, portId);
        if (devicePortIt == mPorts.end()) continue;
        auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
        for (const auto& mixPort : mixPorts) {
            if (std::find(allowedRoutes.begin(), allowedRoutes.end(),
                          make_pair(portId, mixPort.id)) == allowedRoutes.end()) {
                auto mixPortConfig = getSingleConfigForMixPort(isInput, mixPort);
                if (mixPortConfig.has_value()) {
                    return make_pair(devicePortConfig, mixPortConfig.value());
                }
            }
        }
    }
    return {};
}

std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getRoutableSrcSinkPair(bool isInput) const {
    if (isInput) {
        for (const auto& route : mRoutes) {
            auto srcPortIdIt = std::find_if(
                    route.sourcePortIds.begin(), route.sourcePortIds.end(),
                    [&](const auto& portId) { return mAttachedSourceDevicePorts.count(portId); });
            if (srcPortIdIt == route.sourcePortIds.end()) continue;
            const auto devicePortIt = findById<AudioPort>(mPorts, *srcPortIdIt);
            const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
            if (devicePortIt == mPorts.end() || mixPortIt == mPorts.end()) continue;
            auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
            auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
            if (!mixPortConfig.has_value()) continue;
            return std::make_pair(devicePortConfig, mixPortConfig.value());
        }
    } else {
        for (const auto& route : mRoutes) {
            if (mAttachedSinkDevicePorts.count(route.sinkPortId) == 0) continue;
            const auto mixPortIt = findById<AudioPort>(mPorts, route.sourcePortIds[0]);
            const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
            if (devicePortIt == mPorts.end() || mixPortIt == mPorts.end()) continue;
            auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
            auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
            if (!mixPortConfig.has_value()) continue;
            return std::make_pair(mixPortConfig.value(), devicePortConfig);
        }
    }
    return {};
}

std::vector<ModuleConfig::SrcSinkGroup> ModuleConfig::getRoutableSrcSinkGroups(bool isInput) const {
    std::vector<SrcSinkGroup> result;
    if (isInput) {
        for (const auto& route : mRoutes) {
            std::vector<int32_t> srcPortIds;
            std::copy_if(route.sourcePortIds.begin(), route.sourcePortIds.end(),
                         std::back_inserter(srcPortIds), [&](const auto& portId) {
                             return mAttachedSourceDevicePorts.count(portId);
                         });
            if (srcPortIds.empty()) continue;
            const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
            if (mixPortIt == mPorts.end()) continue;
            auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
            if (!mixPortConfig.has_value()) continue;
            std::vector<SrcSinkPair> pairs;
            for (const auto srcPortId : srcPortIds) {
                const auto devicePortIt = findById<AudioPort>(mPorts, srcPortId);
                if (devicePortIt == mPorts.end()) continue;
                // Using all configs for every source would be too much.
                auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
                pairs.emplace_back(devicePortConfig, mixPortConfig.value());
            }
            if (!pairs.empty()) {
                result.emplace_back(route, std::move(pairs));
            }
        }
    } else {
        for (const auto& route : mRoutes) {
            if (mAttachedSinkDevicePorts.count(route.sinkPortId) == 0) continue;
            const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
            if (devicePortIt == mPorts.end()) continue;
            auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
            std::vector<SrcSinkPair> pairs;
            for (const auto srcPortId : route.sourcePortIds) {
                const auto mixPortIt = findById<AudioPort>(mPorts, srcPortId);
                if (mixPortIt == mPorts.end()) continue;
                // Using all configs for every source would be too much.
                auto mixPortConfig = getSingleConfigForMixPort(isInput, *mixPortIt);
                if (mixPortConfig.has_value()) {
                    pairs.emplace_back(mixPortConfig.value(), devicePortConfig);
                }
            }
            if (!pairs.empty()) {
                result.emplace_back(route, std::move(pairs));
            }
        }
    }
    return result;
}

std::string ModuleConfig::toString() const {
    std::string result;
    result.append("Ports: ");
    result.append(android::internal::ToString(mPorts));
    result.append("\nInitial configs: ");
    result.append(android::internal::ToString(mInitialConfigs));
    result.append("\nAttached sink device ports: ");
    result.append(android::internal::ToString(mAttachedSinkDevicePorts));
    result.append("\nAttached source device ports: ");
    result.append(android::internal::ToString(mAttachedSourceDevicePorts));
    result.append("\nExternal device ports: ");
    result.append(android::internal::ToString(mExternalDevicePorts));
    result.append("\nRoutes: ");
    result.append(android::internal::ToString(mRoutes));
    return result;
}

static size_t combineAudioConfigs(const AudioPort& port, const AudioProfile& profile,
                                  std::vector<AudioPortConfig>* result) {
    const size_t newConfigCount = profile.channelMasks.size() * profile.sampleRates.size();
    result->reserve(result->capacity() + newConfigCount);
    for (auto channelMask : profile.channelMasks) {
        for (auto sampleRate : profile.sampleRates) {
            AudioPortConfig config{};
            config.portId = port.id;
            Int sr;
            sr.value = sampleRate;
            config.sampleRate = sr;
            config.channelMask = channelMask;
            config.format = profile.format;
            config.flags = port.flags;
            config.ext = port.ext;
            result->push_back(std::move(config));
        }
    }
    return newConfigCount;
}

static bool isDynamicProfile(const AudioProfile& profile) {
    return (profile.format.type == AudioFormatType::DEFAULT && profile.format.encoding.empty()) ||
           profile.sampleRates.empty() || profile.channelMasks.empty();
}

std::vector<AudioPort> ModuleConfig::findMixPorts(
        bool isInput, bool attachedOnly, bool singlePort,
        const std::function<bool(const AudioPort&)>& pred) const {
    std::vector<AudioPort> result;
    const auto mixPorts = getMixPorts(isInput, attachedOnly);
    for (auto mixPortIt = mixPorts.begin(); mixPortIt != mixPorts.end();) {
        mixPortIt = std::find_if(mixPortIt, mixPorts.end(), pred);
        if (mixPortIt == mixPorts.end()) break;
        result.push_back(*mixPortIt++);
        if (singlePort) break;
    }
    return result;
}

std::vector<AudioPortConfig> ModuleConfig::generateAudioMixPortConfigs(
        const std::vector<AudioPort>& ports, bool isInput, bool singleProfile) const {
    std::vector<AudioPortConfig> result;
    for (const auto& mixPort : ports) {
        if (getAttachedDevicesPortsForMixPort(isInput, mixPort).empty()) {
            continue;
        }
        for (const auto& profile : mixPort.profiles) {
            if (isDynamicProfile(profile)) continue;
            combineAudioConfigs(mixPort, profile, &result);
            if (singleProfile && !result.empty()) {
                result.resize(1);
                return result;
            }
        }
    }
    return result;
}

std::vector<AudioPortConfig> ModuleConfig::generateAudioDevicePortConfigs(
        const std::vector<AudioPort>& ports, bool singleProfile) const {
    std::vector<AudioPortConfig> result;
    for (const auto& devicePort : ports) {
        const size_t resultSizeBefore = result.size();
        for (const auto& profile : devicePort.profiles) {
            combineAudioConfigs(devicePort, profile, &result);
            if (singleProfile && !result.empty()) {
                result.resize(1);
                return result;
            }
        }
        if (resultSizeBefore == result.size()) {
            std::copy_if(mInitialConfigs.begin(), mInitialConfigs.end(), std::back_inserter(result),
                         [&](const auto& config) { return config.portId == devicePort.id; });
            if (resultSizeBefore == result.size()) {
                AudioPortConfig empty;
                empty.portId = devicePort.id;
                empty.ext = devicePort.ext;
                result.push_back(empty);
            }
        }
        if (singleProfile) return result;
    }
    return result;
}

bool ModuleConfig::isMmapSupported() const {
    const std::vector<AudioPort> mmapOutMixPorts =
            getMmapOutMixPorts(false /*attachedOnly*/, false /*singlePort*/);
    const std::vector<AudioPort> mmapInMixPorts =
            getMmapInMixPorts(false /*attachedOnly*/, false /*singlePort*/);
    return !mmapOutMixPorts.empty() || !mmapInMixPorts.empty();
}
