/*
 * Copyright (C) 2025 Intel Corporation.
 *
 * 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 INTEL_CCA_H_
#define INTEL_CCA_H_

#include "IIPUAic.h"
#include "IntelCCABase.h"

namespace cca {

/**
 * @brief SegMapQueue for internal usage.
 */
class SegMapQueue;

/*!
 * \brief Main entrance of CCA Flow library.
 */
class LIBEXPORT IntelCCA : public IntelCCABase {
 public:
    /*!
     * \brief Constructor for IntelCCA.
     */
    IntelCCA();

    /*!
     * \brief Destructor for IntelCCA.
     */
    virtual ~IntelCCA();

    /*!
     * \brief Reinitialize AIC.
     *
     * \param[in] aic_id Mandatory. The ID for AIC handle. Default is -1.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    ia_err reinitAic(const int32_t aic_id = -1);

    /*!
     * \brief Reinitialize AIQ.
     *
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    ia_err reinitAiq();

    /*!
     * \brief Configure the kernels of the pipeline, register all kernel offsets, and return the
     * terminal number and payload size.
     *
     * \param[in] conf Kernel list for the pipeline.
     * \param[in] offset Kernel offsets.
     * \param[out] termConfig Terminal payload number and size.
     * \param[in] aicId (Optional) The ID for AIC handle. Default is -1.
     * \param[in] statsBufToTermId (Optional) Mapping from statistics buffer type to terminal ID.
     * Default is nullptr.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    ia_err configAIC(const cca_aic_config &conf, const cca_aic_kernel_offset &offset,
                     cca_aic_terminal_config &termConfig, int32_t aicId = -1,
                     const int32_t *statsBufToTermId = nullptr);

    /*!
     * \brief Register payload buffers to AIC.
     *
     * \param[out] termConfig Terminal payload.
     * \param[in] aicId (Optional) The ID for AIC handle. Default is -1.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    ia_err registerAICBuf(const cca_aic_terminal_config &termConfig, int32_t aicId = -1);

    /*!
     * \brief Query the PAL buffer filled by kernel parameters calculated by AIC.
     *
     * \param[out] termConfig Terminal payload.
     * \param[in] aicId (Optional) The ID for AIC handle. Default is -1.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    ia_err getAICBuf(cca_aic_terminal_config &termConfig, int32_t aicId = -1);

    /*!
     * \brief Decode statistics from HW.
     * Parse and decode different statistics from HW including AE/AWB/DVS/HDR.
     *
     * \param[in] groupId Statistics binary generated by CB (groupId).
     * \param[in] seqId Statistics sequence number.
     * \param[in] aicId (Optional) The ID for AIC handle. Default is -1.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    ia_err decodeStats(int32_t groupId, int64_t seqId, int32_t aicId = -1, bool skip = false);

    /*!
     * \brief Run AIC to get PAL binary for IPU7 HW.
     * Calculate the PAL parameters according to 3A+ results and manual settings.
     *
     * \param[in] frameId Indicate PAL results for a specific frame.
     * \param[in] params Manual settings for IPU pipeline.
     * \param[out] output Binary array of IPU parameters for each CB.
     * \param[in] bitmap Bitmap to decide which CB will be run. Default is UINT8_MAX.
     * \param[in] aicId (Optional) The ID for AIC handle. Default is -1.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    ia_err runAIC(uint64_t frameId, const cca_pal_input_params &params,
                  cca_multi_pal_output &output, uint8_t bitmap = UINT8_MAX, int32_t aicId = -1);

    /*!
     * \brief Set input information about the segmap.
     *
     * \param[in] params segmap information about a frame.
     * \return Error code for status. zero on success, non-zero on failure
     */
    ia_err setSegMap(const ia_aiq_segmap_input_params *params);

    /*!
     * \brief Get PAL input data.
     *
     * \param[in] stream_id Stream ID.
     * \param[in] seq_id Sequence ID.
     * \param[out] aic_output_common AIC output common binary data.
     * \param[out] tuning_output Tuning output binary data.
     * \param[in] aicId (Optional) The ID for AIC handle. Default is -1.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    ia_err GetPalInputData(uint32_t stream_id, int32_t seq_id, ia_binary_data *aic_output_common,
                           ia_binary_data *tuning_output, int32_t aicId = -1);

    /*!
     * \brief Run AIC to get PAL binary for IPU7 HW.
     * Calculate the PAL parameters according to 3A+ results and manual settings.
     *
     * \param[in] frameId Indicate PAL results for a specific frame.
     * \param[in] params Manual settings for IPU pipeline.
     * \param[in] aicId (Optional) The ID for AIC handle. Default is -1.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    ia_err runAIC(uint64_t frameId, const cca_pal_input_params &params, int32_t aicId = -1);

    /*!
     * \brief Run kernels to get PAL binary for IPU7 HW.
     * Calculate the PAL parameters according to 3A+ results and manual settings.
     *
     * \param[in] groupId Statistics binary generated by CB (groupId).
     * \param[in] frameId Indicate PAL results for a specific frame.
     * \param[out] output_data Binary array of IPU parameters for each CB.
     * \param[in] fragment_index Fragment index. Default is 0U.
     * \param[in] aicId (Optional) The ID for AIC handle. Default is -1.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    ia_err runKernels(uint32_t groupId, uint64_t frameId, cca_binary_data *output_data,
                      uint32_t fragment_index = 0U, int32_t aicId = -1);

    /*!
     * \brief Get PAC output size.
     *
     * \param[in] programGroup Program group.
     * \return PAC output size.
     */
    static uint32_t getPacOutputSize(const cca_program_group &programGroup);

    /*!
     * \brief Update configuration resolutions.
     *
     * \param[in] conf Configuration.
     * \param[in] aicId The ID for AIC handle.
     * \param[in] isKeyResolutionChanged Flag indicating if key resolution has changed.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    ia_err updateConfigurationResolutions(const cca_aic_config &conf, int32_t aicId,
                                          bool isKeyResolutionChanged);

    /*!
     * \brief Query statistics buffer.
     *
     * \param[in] status Statistics buffer status.
     * \param[in] frameId Frame ID. Default is cca::INVALID_FRAME_ID.
     * \return Pointer to the frame statistics.
     */
    cca_frame_stats *queryStatsBuf(cca_stats_buf_status status,
                                   uint64_t frameId = cca::INVALID_FRAME_ID);

 private:
    /*!
     * \brief Set input statistics and information (e.g., faces) about the captured image.
     * CCA Flow algorithms need various information about the conditions in which the frame and
     * statistics were captured in order to calculate new parameters.
     *
     * \param[in] params Input parameters containing statistics information about a frame.
     * \param[in] aiqResults AIQ results from the corresponding frame.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    virtual ia_err setStatsToAiq(const cca_stats_params &params,
                                 const cca_aiq_results_storage &aiqResults) override;

    /*!
     * \brief Set LTM tuning data.
     *
     * \param[in] tuning_data_ptr Pointer to the tuning data.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    virtual ia_err setLtmTuning(const ia_binary_data *tuning_data_ptr) override {
        (void)tuning_data_ptr;
        return ia_err_none;
    }

    /*!
     * \brief Update LTM result.
     *
     * \param[in] results Pointer to the 3A+ results.
     */
    virtual void updateLtmResult(cca_3a_plus_results *results) override {
        if (results != nullptr) {
            results->drc_params = nullptr;
            results->ltm_results = nullptr;
        }
    }

    /*!
     * \brief Create a new AIC instance.
     */
    virtual void newAic() override;

    /*!
     * \brief Delete the AIC instance.
     */
    virtual void deleteAic() override;

    /*!
     * \brief Initialize AIC.
     *
     * \param[in] aiqb Pointer to the AIQB binary data.
     * \param[in] cmc Pointer to the CMC data.
     * \param[in] max_stats_width Maximum statistics width.
     * \param[in] max_stats_height Maximum statistics height.
     * \param[in] max_num_stats_in Maximum number of statistics inputs.
     * \param[in] mkn Pointer to the MKN data.
     * \param[in] aic_stream_ids AIC stream IDs.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    virtual ia_err initAic(const ia_binary_data *aiqb, const ia_cmc_t *cmc,
                           uint32_t max_stats_width, uint32_t max_stats_height,
                           uint32_t max_num_stats_in, const ia_mkn *mkn,
                           const cca_stream_ids &aic_stream_ids) override;

    /*!
     * \brief Update AIC tuning.
     *
     * \param[in] aiqb Pointer to the AIQB binary data.
     * \param[in] cmc Pointer to the CMC data.
     * \param[in] streamId (Optional) Stream ID. Default is -1.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    virtual ia_err updateAicTuning(const ia_binary_data *aiqb, const ia_cmc_t *cmc,
                                   int32_t streamId = -1) override;

    /*!
     * \brief Get DVS statistics from AIC.
     *
     * \param[out] stats Pointer to the DVS statistics.
     * \return Error code for status. Zero on success, non-zero on failure.
     */
    virtual ia_err getDvsStatsAic(ia_dvs_statistics *stats) override;

 private:
    ia_ccat_frame_parameters mFrameParameters{}; /*!< Frame parameters. */
    IPU7Aic *mAic;                               /*!< Pointer to the IPU7 AIC instance. */
    SegMapQueue *mSegMapQueue;                   /*!< Pointer to the SegMapQueue instance. */
};

}  // namespace cca

#endif  // INTEL_CCA_H_
