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

#define LOG_TAG "ConversionHelperAidl"

#include <memory>

#include <media/AidlConversionUtil.h>
#include <utils/Log.h>

#include "ConversionHelperAidl.h"

using aidl::android::aidl_utils::statusTFromBinderStatus;
using aidl::android::hardware::audio::core::VendorParameter;
using aidl::android::media::audio::IHalAdapterVendorExtension;

namespace android {

status_t parseAndGetVendorParameters(
        std::shared_ptr<IHalAdapterVendorExtension> vendorExt,
        const VendorParametersRecipient& recipient,
        const AudioParameter& parameterKeys,
        String8* values) {
    using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
    if (parameterKeys.size() == 0) return OK;
    const String8 rawKeys = parameterKeys.keysToString();
    if (vendorExt == nullptr) {
        ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeys.c_str());
        return OK;
    }

    std::vector<std::string> parameterIds;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameterIds(
                            ParameterScope(recipient.index()),
                            std::string(rawKeys.c_str()), &parameterIds)));
    if (parameterIds.empty()) return OK;

    std::vector<VendorParameter> parameters;
    if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
        auto module = std::get<static_cast<int>(ParameterScope::MODULE)>(recipient);
        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->getVendorParameters(
                                parameterIds, &parameters)));
    } else if (recipient.index() == static_cast<int>(ParameterScope::STREAM)) {
        auto stream = std::get<static_cast<int>(ParameterScope::STREAM)>(recipient);
        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->getVendorParameters(
                                parameterIds, &parameters)));
    } else {
        LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu",
                __func__, recipient.index());
    }
    if (!parameters.empty()) {
        std::string vendorParameters;
        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->processVendorParameters(
                                ParameterScope(recipient.index()),
                                parameters, &vendorParameters)));
        // Re-parse the vendor-provided string to ensure that it is correct.
        AudioParameter reparse(String8(vendorParameters.c_str()));
        if (reparse.size() != 0) {
            if (values->length() > 0) {
                values->append(";");
            }
            values->append(reparse.toString().c_str());
        }
    }
    return OK;
}

status_t parseAndSetVendorParameters(
        std::shared_ptr<IHalAdapterVendorExtension> vendorExt,
        const VendorParametersRecipient& recipient,
        const AudioParameter& parameters) {
    using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
    if (parameters.size() == 0) return OK;
    const String8 rawKeysAndValues = parameters.toString();
    if (vendorExt == nullptr) {
        ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeysAndValues.c_str());
        return OK;
    }

    std::vector<VendorParameter> syncParameters, asyncParameters;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameters(
                            ParameterScope(recipient.index()),
                            std::string(rawKeysAndValues.c_str()),
                            &syncParameters, &asyncParameters)));
    if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
        auto module = std::get<static_cast<int>(ParameterScope::MODULE)>(recipient);
        if (!syncParameters.empty()) {
            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters(
                                    syncParameters, false /*async*/)));
        }
        if (!asyncParameters.empty()) {
            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters(
                                    asyncParameters, true /*async*/)));
        }
    } else if (recipient.index() == static_cast<int>(ParameterScope::STREAM)) {
        auto stream = std::get<static_cast<int>(ParameterScope::STREAM)>(recipient);
        if (!syncParameters.empty()) {
            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters(
                                    syncParameters, false /*async*/)));
        }
        if (!asyncParameters.empty()) {
            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters(
                                    asyncParameters, true /*async*/)));
        }
    } else {
        LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu",
                __func__, recipient.index());
    }
    return OK;
}

} // namespace android
