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

#ifndef C_CODEC_CONFIG_H_
#define C_CODEC_CONFIG_H_

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

#include <C2Component.h>
#include <C2Config.h>
#include <C2Debug.h>

#include <codec2/hidl/client.h>
#include <utils/RefBase.h>

#include "InputSurfaceWrapper.h"
#include "ReflectedParamUpdater.h"

namespace android {

struct AMessage;
struct CodecParameterDescriptor;
class NativeHandle;
struct StandardParams;

/**
 * Struct managing the codec configuration for CCodec.
 */
struct CCodecConfig {
    /**
     * Domain consists of a bitmask divided into fields, and specifiers work by excluding other
     * values in those domains.
     *
     * Component domains are composed by or-ing the individual IS_ constants, e.g.
     * IS_DECODER | IS_AUDIO.
     *
     * Config specifiers are composed by or-ing the individual mask constants, and
     * and-ing these groups: e.g. (DECODER | ENCODER) & AUDIO.
     *
     * The naming of these constants was to limit the length of mask names as these are used more
     * commonly as masks.
     */
    enum Domain : uint32_t {
        // component domain (domain & kind)
        GUARD_BIT   = (1 << 1),   ///< this is to prevent against accidental && or || usage
        IS_AUDIO    = (1 << 2),   ///< for audio codecs
        IS_VIDEO    = (1 << 3),   ///< for video codecs
        IS_IMAGE    = (1 << 4),   ///< for image codecs
        OTHER_DOMAIN = (1 << 5),  ///< for other domains

        IS_ENCODER  = (1 << 6),   ///< for encoders
        IS_DECODER  = (1 << 7),   ///< for decoders
        OTHER_KIND  = (1 << 8),   ///< for other domains

        // config domain
        IS_PARAM    = (1 << 9),   ///< for setParameter
        IS_CONFIG   = (1 << 10),  ///< for configure
        IS_READ     = (1 << 11),  ///< for getFormat

        // port domain
        IS_INPUT    = (1 << 12),  ///< for input port (getFormat)
        IS_OUTPUT   = (1 << 13),  ///< for output port (getFormat)
        IS_RAW      = (1 << 14),  ///< for raw port (input-encoder, output-decoder)
        IS_CODED    = (1 << 15),  ///< for coded port (input-decoder, output-encoder)

        ALL     = ~0U,
        NONE    = 0,

        AUDIO   = ~(IS_IMAGE | IS_VIDEO | OTHER_DOMAIN),
        VIDEO   = ~(IS_AUDIO | IS_IMAGE | OTHER_DOMAIN),
        IMAGE   = ~(IS_AUDIO | IS_VIDEO | OTHER_DOMAIN),

        DECODER = ~(IS_ENCODER | OTHER_KIND),
        ENCODER = ~(IS_DECODER | OTHER_KIND),

        PARAM   = ~(IS_CONFIG | IS_READ),
        CONFIG  = ~(IS_PARAM  | IS_READ),
        READ    = ~(IS_CONFIG | IS_PARAM),

        INPUT   = ~(IS_OUTPUT | IS_RAW    | IS_CODED),
        OUTPUT  = ~(IS_INPUT  | IS_RAW    | IS_CODED),
        RAW     = ~(IS_INPUT  | IS_OUTPUT | IS_CODED),
        CODED   = ~(IS_INPUT  | IS_RAW    | IS_OUTPUT),
    };

    // things required to manage formats
    std::vector<std::shared_ptr<C2ParamDescriptor>> mParamDescs;
    std::shared_ptr<C2ParamReflector> mReflector;

    std::shared_ptr<ReflectedParamUpdater> mParamUpdater;

    Domain mDomain; // component domain
    Domain mInputDomain; // input port domain
    Domain mOutputDomain; // output port domain
    std::string mCodingMediaType;  // media type of the coded stream

    // standard MediaCodec to Codec 2.0 params mapping
    std::shared_ptr<StandardParams> mStandardParams;

    std::set<C2Param::Index> mSupportedIndices; ///< indices supported by the component
    std::set<C2Param::Index> mSubscribedIndices; ///< indices to subscribe to
    size_t mSubscribedIndicesSize; ///< count of currently subscribed indices

    sp<AMessage> mInputFormat;
    sp<AMessage> mOutputFormat;

    bool mUsingSurface; ///< using input or output surface
    bool mBuffersBoundToCodec; ///< whether buffers are bound to codecs or not.

    std::shared_ptr<InputSurfaceWrapper> mInputSurface;
    std::unique_ptr<InputSurfaceWrapper::Config> mISConfig;
    android_dataspace mInputSurfaceDataspace;

    /// the current configuration. Updated after configure() and based on configUpdate in
    /// onWorkDone
    std::map<C2Param::Index, std::unique_ptr<C2Param>> mCurrentConfig;

    typedef std::function<c2_status_t(std::unique_ptr<C2Param>&)> LocalParamValidator;

    /// Parameter indices tracked in current config that are not supported by the component.
    /// these are provided so that optional parameters can remain in the current configuration.
    /// as such, these parameters have no dependencies. TODO: use C2InterfaceHelper for this.
    /// For now support a validation function.
    std::map<C2Param::Index, LocalParamValidator> mLocalParams;

    /// Vendor field name -> desc map.
    std::map<std::string, std::shared_ptr<C2ParamDescriptor>> mVendorParams;

    std::set<std::string> mLastConfig;

    /// Tunneled codecs
    bool mTunneled;
    sp<NativeHandle> mSidebandHandle;

    bool mPushBlankBuffersOnStop;

    CCodecConfig();

    /// initializes the members required to manage the format: descriptors, reflector,
    /// reflected param helper, domain, standard params, and subscribes to standard
    /// indices.
    status_t initialize(
            const std::shared_ptr<C2ParamReflector> &client,
            const std::shared_ptr<Codec2Client::Configurable> &configurable);

    /**
     * Adds a locally maintained parameter. This is used for output configuration that can be
     * appended to the output buffers in case it is not supported by the component.
     */
    template<typename T>
    bool addLocalParam(
            const std::string &name,
            C2ParamDescriptor::attrib_t attrib = C2ParamDescriptor::IS_READ_ONLY,
            std::function<c2_status_t(std::unique_ptr<T>&)> validator_ =
                std::function<c2_status_t(std::unique_ptr<T>&)>()) {
        C2Param::Index index = T::PARAM_TYPE;
        if (mSupportedIndices.count(index) || mLocalParams.count(index)) {
            if (mSupportedIndices.count(index)) {
                mSubscribedIndices.emplace(index);
            }
            ALOGD("ignoring local param %s (%#x) as it is already %s",
                    name.c_str(), (uint32_t)index, mSupportedIndices.count(index) ? "supported" : "local");
            return false; // already supported by the component or already added
        }

        // wrap typed validator into untyped validator
        LocalParamValidator validator;
        if (validator_) {
            validator = [validator_](std::unique_ptr<C2Param>& p){
                c2_status_t res = C2_BAD_VALUE;
                std::unique_ptr<T> typed(static_cast<T*>(p.release()));
                // if parameter is correctly typed
                if (T::From(typed.get())) {
                    res = validator_(typed);
                    p.reset(typed.release());
                }
                return res;
            };
        }

        mLocalParams.emplace(index, validator);
        mParamUpdater->addStandardParam<T>(name, attrib);
        return true;
    }

    /**
     * Adds a locally maintained parameter with a default value.
     */
    template<typename T>
    bool addLocalParam(
            std::unique_ptr<T> default_,
            const std::string &name,
            C2ParamDescriptor::attrib_t attrib = C2ParamDescriptor::IS_READ_ONLY,
            std::function<c2_status_t(std::unique_ptr<T>&)> validator_ =
                std::function<c2_status_t(std::unique_ptr<T>&)>()) {
        if (addLocalParam<T>(name, attrib, validator_)) {
            if (validator_) {
                c2_status_t err = validator_(default_);
                if (err != C2_OK) {
                    ALOGD("default value for %s is invalid => %s", name.c_str(), asString(err));
                    return false;
                }
            }
            mCurrentConfig[T::PARAM_TYPE] = std::move(default_);
            return true;
        }
        return false;
    }

    template<typename T>
    bool addLocalParam(
            T *default_, const std::string &name,
            C2ParamDescriptor::attrib_t attrib = C2ParamDescriptor::IS_READ_ONLY,
            std::function<c2_status_t(std::unique_ptr<T>&)> validator_ =
                std::function<c2_status_t(std::unique_ptr<T>&)>()) {
        return addLocalParam(std::unique_ptr<T>(default_), name, attrib, validator_);
    }

    /// Applies configuration updates, and updates format in the specific domain.
    /// Returns true if formats were updated
    /// \param domain input/output bitmask
    bool updateConfiguration(
            std::vector<std::unique_ptr<C2Param>> &configUpdate, Domain domain);

    /// Updates formats in the specific domain. Returns true if any of the formats have changed.
    /// \param domain input/output bitmask
    bool updateFormats(Domain domain);

    /**
     * Applies SDK configurations in a specific configuration domain.
     * Updates relevant input/output formats and subscribes to parameters specified in the
     * configuration.
     * \param domain config/setParam bitmask
     * \param blocking blocking mode to use with the component
     */
    status_t getConfigUpdateFromSdkParams(
            std::shared_ptr<Codec2Client::Configurable> configurable,
            const sp<AMessage> &sdkParams, Domain domain,
            c2_blocking_t blocking,
            std::vector<std::unique_ptr<C2Param>> *configUpdate) const;

    /**
     * Applies a configuration update to the component.
     * Updates relevant input/output formats and subscribes to parameters specified in the
     * configuration.
     * \param blocking blocking mode to use with the component
     */
    status_t setParameters(
            std::shared_ptr<Codec2Client::Configurable> configurable,
            std::vector<std::unique_ptr<C2Param>> &configUpdate,
            c2_blocking_t blocking);

    /// Queries subscribed indices (which contains all SDK-exposed values) and updates
    /// input/output formats.
    status_t queryConfiguration(
            const std::shared_ptr<Codec2Client::Configurable> &configurable);

    /// Queries a configuration parameter value. Returns nullptr if the parameter is not
    /// part of the current configuration
    const C2Param *getConfigParameterValue(C2Param::Index index) const;

    /// Subscribe to all vendor parameters.
    status_t subscribeToAllVendorParams(
            const std::shared_ptr<Codec2Client::Configurable> &configurable,
            c2_blocking_t blocking);

    /**
     * Object that can be used to access configuration parameters and if they change.
     */
    template<typename T>
    struct Watcher {
        ~Watcher() = default;

        /// returns true if the value of this configuration has changed
        bool hasChanged() const {
            const C2Param *value = mParent->getConfigParameterValue(mIndex);
            if (value && mValue) {
                return *value != *mValue;
            } else {
                return value != mValue.get();
            }
        }

        /// updates the current value and returns it
        std::shared_ptr<const T> update() {
            const C2Param *value = mParent->getConfigParameterValue(mIndex);
            if (value) {
                mValue = std::shared_ptr<const T>(T::From(C2Param::Copy(*value).release()));
            }
            return mValue;
        }

    private:
        Watcher(C2Param::Index index, const CCodecConfig *parent)
            : mParent(parent), mIndex(index) {
            update();
        }

        friend struct CCodecConfig;

        const CCodecConfig *mParent;
        std::shared_ptr<const T> mValue;
        C2Param::Index mIndex;
    };

    /**
     * Returns a watcher object for a parameter.
     */
    template<typename T>
    Watcher<T> watch(C2Param::Index index = T::PARAM_TYPE) const {
        if (index.type() != T::PARAM_TYPE) {
            __builtin_trap();
        }
        return Watcher<T>(index, this);
    }

    /**
     * Queries supported parameters and put the keys to |names|.
     * TODO: currently this method queries vendor parameter keys only.
     *
     * \return OK if successful.
     *         BAD_VALUE if |names| is nullptr.
     */
    status_t querySupportedParameters(std::vector<std::string> *names);

    /**
     * Describe the parameter with |name|, filling the information into |desc|
     * TODO: currently this method works only for vendor parameters.
     *
     * \return OK if successful.
     *         BAD_VALUE if |desc| is nullptr.
     *         NAME_NOT_FOUND if |name| is not a recognized parameter name.
     */
    status_t describe(const std::string &name, CodecParameterDescriptor *desc);

    /**
     * Find corresponding indices for |names| and subscribe to them.
     */
    status_t subscribeToVendorConfigUpdate(
            const std::shared_ptr<Codec2Client::Configurable> &configurable,
            const std::vector<std::string> &names,
            c2_blocking_t blocking = C2_DONT_BLOCK);

    /**
     * Find corresponding indices for |names| and unsubscribe from them.
     */
    status_t unsubscribeFromVendorConfigUpdate(
            const std::shared_ptr<Codec2Client::Configurable> &configurable,
            const std::vector<std::string> &names,
            c2_blocking_t blocking = C2_DONT_BLOCK);

    /// Adds indices to the subscribed indices, and updated subscription to component
    /// \param blocking blocking mode to use with the component
    status_t subscribeToConfigUpdate(
            const std::shared_ptr<Codec2Client::Configurable> &configurable,
            const std::vector<C2Param::Index> &indices,
            c2_blocking_t blocking = C2_DONT_BLOCK);

private:

    /// initializes the standard MediaCodec to Codec 2.0 params mapping
    void initializeStandardParams();

    /// Gets SDK format from codec 2.0 reflected configuration
    /// \param domain input/output bitmask
    sp<AMessage> getFormatForDomain(
            const ReflectedParamUpdater::Dict &reflected,
            Domain domain) const;

    /**
     * Converts a set of configuration parameters in an AMessage to a list of path-based Codec
     * 2.0 configuration parameters.
     *
     * \param domain config/setParam bitmask
     */
    ReflectedParamUpdater::Dict getReflectedFormat(
            const sp<AMessage> &config, Domain domain) const;
};

DEFINE_ENUM_OPERATORS(CCodecConfig::Domain)

}  // namespace android

#endif  // C_CODEC_H_
