/*
 * Copyright (C) 2023 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.
 */

#pragma once

#include <memory>
#include <map>
#include <set>
#include <utility>
#include <vector>

#include <aidl/android/hardware/audio/core/IModule.h>
#include <media/AidlConversionUtil.h>

#include "Cleanups.h"

namespace android {

class Hal2AidlMapper;
class StreamHalInterface;

// The mapper class is needed because the framework was not yet updated to operate on AIDL-based
// structures directly. Mapper does the job of translating the "legacy" way of identifying ports
// and port configs (by device addresses and I/O handles) into AIDL IDs. Once the framework will
// be updated to provide these IDs directly to libaudiohal, the need for the mapper will cease.
//
// Note that unlike DeviceHalInterface, which sometimes allows a method to return an error,
// but still consider some of the outputs to be valid (for example, in 'open{Input|Output}Stream'),
// 'Hal2AidlMapper' follows the Binder convention. It means that if a method returns an error,
// the outputs may not be initialized at all and should not be considered by the caller.
class Hal2AidlMapper {
  public:
    using Cleanups = Cleanups<Hal2AidlMapper>;

    Hal2AidlMapper(
            const std::string& instance,
            const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module);

    void addStream(const sp<StreamHalInterface>& stream, int32_t portConfigId, int32_t patchId);
    status_t createOrUpdatePatch(
            const std::vector<::aidl::android::media::audio::common::AudioPortConfig>& sources,
            const std::vector<::aidl::android::media::audio::common::AudioPortConfig>& sinks,
            int32_t* patchId, Cleanups* cleanups);
    status_t findPortConfig(
            const ::aidl::android::media::audio::common::AudioDevice& device,
            ::aidl::android::media::audio::common::AudioPortConfig* portConfig);
    status_t getAudioMixPort(
            int32_t ioHandle, ::aidl::android::media::audio::common::AudioPort* port);
    status_t getAudioPortCached(
            const ::aidl::android::media::audio::common::AudioDevice& device,
            ::aidl::android::media::audio::common::AudioPort* port);
    template<typename OutputContainer, typename Func>
    status_t getAudioPorts(OutputContainer* ports, Func converter) {
        return ::aidl::android::convertContainer(mPorts, ports,
                [&converter](const auto& pair) { return converter(pair.second); });
    }
    template<typename OutputContainer, typename Func>
    status_t getAudioRoutes(OutputContainer* routes, Func converter) {
        return ::aidl::android::convertContainer(mRoutes, routes, converter);
    }
    status_t initialize();
    // If the resulting 'mixPortConfig->id' is 0, that means the stream was not created,
    // and 'config' is a suggested config.
    status_t prepareToOpenStream(
        int32_t ioHandle,
        const ::aidl::android::media::audio::common::AudioDevice& device,
        const ::aidl::android::media::audio::common::AudioIoFlags& flags,
        ::aidl::android::media::audio::common::AudioSource source,
        Cleanups* cleanups,
        ::aidl::android::media::audio::common::AudioConfig* config,
        ::aidl::android::media::audio::common::AudioPortConfig* mixPortConfig,
        ::aidl::android::hardware::audio::core::AudioPatch* patch);
    status_t setPortConfig(
        const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
        const std::set<int32_t>& destinationPortIds,
        ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
        Cleanups* cleanups = nullptr);
    status_t releaseAudioPatch(int32_t patchId);
    void resetUnusedPatchesAndPortConfigs();
    status_t setDevicePortConnectedState(
            const ::aidl::android::media::audio::common::AudioPort& devicePort, bool connected);

  private:
    // IDs of ports for connected external devices, and whether they are held by streams.
    using ConnectedPorts = std::map<int32_t /*port ID*/, bool>;
    using Patches = std::map<int32_t /*patch ID*/,
            ::aidl::android::hardware::audio::core::AudioPatch>;
    using PortConfigs = std::map<int32_t /*port config ID*/,
            ::aidl::android::media::audio::common::AudioPortConfig>;
    using Ports = std::map<int32_t /*port ID*/, ::aidl::android::media::audio::common::AudioPort>;
    using Routes = std::vector<::aidl::android::hardware::audio::core::AudioRoute>;
    // Answers the question "whether portID 'first' is reachable from portID 'second'?"
    // It's not a map because both portIDs are known. The matrix is symmetric.
    using RoutingMatrix = std::set<std::pair<int32_t, int32_t>>;
    // There is always a port config ID set. The patch ID is set after stream
    // creation, and can be set to '-1' later if the framework happens to create
    // a patch between the same endpoints. In that case, the ownership of the patch
    // is on the framework.
    using Streams = std::map<wp<StreamHalInterface>,
            std::pair<int32_t /*port config ID*/, int32_t /*patch ID*/>>;

    const std::string mInstance;
    const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;

    bool audioDeviceMatches(const ::aidl::android::media::audio::common::AudioDevice& device,
            const ::aidl::android::media::audio::common::AudioPort& p);
    bool audioDeviceMatches(const ::aidl::android::media::audio::common::AudioDevice& device,
            const ::aidl::android::media::audio::common::AudioPortConfig& p);
    // If the 'result->id' is 0, that means, the config was not created/updated,
    // and the 'result' is a suggestion from the HAL.
    status_t createOrUpdatePortConfig(
            const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
            ::aidl::android::media::audio::common::AudioPortConfig* result, bool *created);
    void eraseConnectedPort(int32_t portId);
    status_t findOrCreatePatch(
        const std::set<int32_t>& sourcePortConfigIds,
        const std::set<int32_t>& sinkPortConfigIds,
        ::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
    status_t findOrCreatePatch(
        const ::aidl::android::hardware::audio::core::AudioPatch& requestedPatch,
        ::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
    status_t findOrCreateDevicePortConfig(
            const ::aidl::android::media::audio::common::AudioDevice& device,
            const ::aidl::android::media::audio::common::AudioConfig* config,
            ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
            bool* created);
    // If the resulting 'portConfig->id' is 0, that means the config was not created,
    // and 'portConfig' is a suggested config.
    status_t findOrCreateMixPortConfig(
            const ::aidl::android::media::audio::common::AudioConfig& config,
            const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
            int32_t ioHandle,
            ::aidl::android::media::audio::common::AudioSource source,
            const std::set<int32_t>& destinationPortIds,
            ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
    status_t findOrCreatePortConfig(
        const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
        const std::set<int32_t>& destinationPortIds,
        ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
    Patches::iterator findPatch(const std::set<int32_t>& sourcePortConfigIds,
            const std::set<int32_t>& sinkPortConfigIds);
    Ports::iterator findPort(const ::aidl::android::media::audio::common::AudioDevice& device);
    Ports::iterator findPort(
            const ::aidl::android::media::audio::common::AudioConfig& config,
            const ::aidl::android::media::audio::common::AudioIoFlags& flags,
            const std::set<int32_t>& destinationPortIds);
    PortConfigs::iterator findPortConfig(
            const ::aidl::android::media::audio::common::AudioDevice& device);
    PortConfigs::iterator findPortConfig(
            const std::optional<::aidl::android::media::audio::common::AudioConfig>& config,
            const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
            int32_t ioHandle);
    bool isPortBeingHeld(int32_t portId);
    bool portConfigBelongsToPort(int32_t portConfigId, int32_t portId) {
        auto it = mPortConfigs.find(portConfigId);
        return it != mPortConfigs.end() && it->second.portId == portId;
    }
    status_t releaseAudioPatches(const std::set<int32_t>& patchIds);
    void resetPatch(int32_t patchId) { (void)releaseAudioPatch(patchId); }
    void resetPortConfig(int32_t portConfigId);
    void resetUnusedPortConfigs();
    status_t updateAudioPort(
            int32_t portId, ::aidl::android::media::audio::common::AudioPort* port);
    status_t updateRoutes();

    Ports mPorts;
    // Remote submix "template" ports (no address specified, no profiles).
    // They are excluded from `mPorts` as their presence confuses the framework code.
    std::optional<::aidl::android::media::audio::common::AudioPort> mRemoteSubmixIn;
    std::optional<::aidl::android::media::audio::common::AudioPort> mRemoteSubmixOut;
    int32_t mDefaultInputPortId = -1;
    int32_t mDefaultOutputPortId = -1;
    PortConfigs mPortConfigs;
    std::set<int32_t> mInitialPortConfigIds;
    Patches mPatches;
    Routes mRoutes;
    RoutingMatrix mRoutingMatrix;
    Streams mStreams;
    ConnectedPorts mConnectedPorts;
    std::pair<int32_t, ::aidl::android::media::audio::common::AudioPort>
            mDisconnectedPortReplacement;
};

}  // namespace android
