/*
 * Copyright (c) 2019-2020, NVIDIA CORPORATION.  All rights reserved.
 *
 * NVIDIA CORPORATION and its licensors retain all intellectual property
 * and proprietary rights in and to this software, related documentation
 * and any modifications thereto.  Any use, reproduction, disclosure or
 * distribution of this software and related documentation without an express
 * license agreement from NVIDIA CORPORATION is strictly prohibited.
 */

#ifndef _CNVMMAX96712CAMERAMODULE_HPP_
#define _CNVMMAX96712CAMERAMODULE_HPP_

#include "ModuleIF/CNvMCameraModule.hpp"
#include "SensorIF/CNvMSensor.hpp"
#include "EEPROMIF/CNvMEEPROM.hpp"
#include "SerializerIF/CNvMSerializer.hpp"
#include "TransportLinkIF/CNvMTransportLink.hpp"
#include "NvSIPLPlatformCfg.hpp"

namespace nvsipl
{

class CNvMMAX96712CameraModule : public CNvMCameraModule
{
public:
    SIPLStatus SetConfig(const CameraModuleConfig *cameraModuleConfig, const uint8_t linkIndex) override final;

    SIPLStatus Init() override final;

    SIPLStatus PostInit() override final;

    SIPLStatus Start() override final;

    SIPLStatus Stop() override final;

    SIPLStatus Reconfigure() override final;

    SIPLStatus ReadEEPROMData(const std::uint16_t address,
                              const std::uint32_t length,
                              std::uint8_t * const buffer) override final;
#if !NV_IS_SAFETY
    SIPLStatus WriteEEPROMData(const std::uint16_t address,
                               const std::uint32_t length,
                               std::uint8_t * const buffer) override final;
#endif // !NV_IS_SAFETY

    SIPLStatus ToggleLED(bool enable) override;

    SIPLStatus Deinit() override final;

    Property* GetCameraModuleProperty() override final;

    SIPLStatus CreateCDIDevice(DevBlkCDIRootDevice* cdiRoot) override final;

    uint16_t GetPowerOnDelayMs() override;

    std::string GetSupportedDeserailizer() override final;

protected:
    enum ModuleComponent {
        MODULE_COMPONENT_SENSOR = 0,
        MODULE_COMPONENT_EEPROM
    };

    std::unique_ptr<CNvMSensor> m_upSensor;

    std::unique_ptr<CNvMEEPROM> m_upEeprom = NULL;

    std::unique_ptr<CNvMSerializer> m_upSerializer;

    std::unique_ptr<CNvMTransportLink> m_upTransport;

    std::unique_ptr<Property> m_upCameraModuleProperty;

    std::unique_ptr<ConnectionProperty> m_upCameraModuleConnectionProperty;

    std::unique_ptr<CNvMSensor> m_broadcastSensor;

    uint8_t m_linkIndex;

    uint8_t m_initLinkMask;

    bool m_groupInitProg; // Indicate if the homogeneous camera support enabled or not

    //! Device params needs to be cached to support reinitialization
    CNvMDevice::DeviceParams m_oDeviceParams;

    SerInfo m_oSerInfo;

    SensorInfo m_oSensorInfo;

    std::string m_sModuleName;

    DevBlkCDIRootDevice* m_pCDIRoot;

    CNvMDeserializer *m_pDeserializer;

    virtual void SetSensorConnectionProperty(ConnectionProperty::SensorConnectionProperty *sensorConnectionProperty);

    virtual SIPLStatus SetConfigModule(const SensorInfo *sensorInfo, CNvMDevice::DeviceParams *params) = 0;

    virtual SIPLStatus DetectModule() = 0;

    virtual SIPLStatus InitModule() = 0;

    virtual SIPLStatus StartModule() = 0;

    virtual SIPLStatus StopModule() = 0;

    virtual SIPLStatus DeinitModule() = 0;

    virtual DevBlkCDIDeviceDriver *GetCDIDeviceDriver() = 0;

    virtual DevBlkCDIDeviceDriver *GetCDIDeviceDriver(ModuleComponent component);

    virtual std::unique_ptr<CNvMDevice::DriverContext> GetCDIDeviceContext() = 0;

    virtual std::unique_ptr<CNvMSerializer> CreateNewSerializer() = 0;

    virtual std::unique_ptr<CNvMTransportLink> CreateNewTransportLink() = 0;

    std::unique_ptr<CNvMSerializer> CreateBroadcastSerializer();

    std::unique_ptr<CNvMSensor> CreateBroadcastSensor();

private:
    void SetupConnectionProperty(const CameraModuleConfig *cameraModuleConfig, const uint8_t linkIndex);
};


} // end of namespace

#endif /* _CNVMMAX96712CAMERAMODULE_HPP_ */
