#ifndef BSP_Q7S_OBJECTFACTORY_H_
#define BSP_Q7S_OBJECTFACTORY_H_

#include <fsfw/returnvalues/returnvalue.h>
#include <fsfw_hal/linux/spi/SpiComIF.h>
#include <mission/acs/gyroAdisHelpers.h>
#include <mission/com/CcsdsIpCoreHandler.h>
#include <mission/com/PersistentLogTmStoreTask.h>
#include <mission/genericFactory.h>
#include <mission/system/objects/Stack5VHandler.h>
#include <mission/tcs/HeaterHandler.h>
#include <mission/tmtc/CfdpTmFunnel.h>
#include <mission/tmtc/PusTmFunnel.h>

#include <atomic>
#include <string>

#include "bsp_q7s/fs/SdCardManager.h"

class LinuxLibgpioIF;
class SerialComIF;
class SpiComIF;
class I2cComIF;
class PowerSwitchIF;
class HealthTableIF;
class AcsBoardAssembly;
class GpioIF;

extern std::atomic_bool PTME_LOCKED;

namespace ObjectFactory {

struct CcsdsComponentArgs {
  CcsdsComponentArgs(LinuxLibgpioIF& gpioIF, StorageManagerIF& ipcStore, StorageManagerIF& tmStore,
                     PersistentTmStores& stores, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel,
                     CcsdsIpCoreHandler** ipCoreHandler, uint32_t pdecCfgMemBaseAddr,
                     uint32_t pdecRamBaseAddr)
      : gpioComIF(gpioIF),
        ipcStore(ipcStore),
        tmStore(tmStore),
        stores(stores),
        pusFunnel(pusFunnel),
        cfdpFunnel(cfdpFunnel),
        ipCoreHandler(ipCoreHandler),
        pdecCfgMemBaseAddr(pdecCfgMemBaseAddr),
        pdecRamBaseAddr(pdecRamBaseAddr) {}
  LinuxLibgpioIF& gpioComIF;
  StorageManagerIF& ipcStore;
  StorageManagerIF& tmStore;
  PersistentTmStores& stores;
  PusTmFunnel& pusFunnel;
  CfdpTmFunnel& cfdpFunnel;
  CcsdsIpCoreHandler** ipCoreHandler;
  uint32_t pdecCfgMemBaseAddr;
  uint32_t pdecRamBaseAddr;
  MessageQueueId_t normalLiveTmDest = MessageQueueIF::NO_QUEUE;
  MessageQueueId_t cfdpLiveTmDest = MessageQueueIF::NO_QUEUE;
};

void setStatics();
void produce(void* args);

void createCommunicationInterfaces(LinuxLibgpioIF** gpioComIF, SerialComIF** uartComIF,
                                   SpiComIF** spiMainComIF, I2cComIF** i2cComIF);
void createPcduComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF** pwrSwitcher,
                          bool enableHkSets);
void createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* spiComIF,
                            PowerSwitchIF* pwrSwitcher, Stack5VHandler& stackHandler);
void createTmpComponents(std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd);
void createRadSensorChipSelect(LinuxLibgpioIF* gpioIF);
ReturnValue_t createRadSensorComponent(LinuxLibgpioIF* gpioComIF, Stack5VHandler& handler);
void createAcsBoardGpios(GpioCookie& cookie);
void createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF* gpioComIF, SerialComIF* uartComIF,
                              PowerSwitchIF& pwrSwitcher, bool enableHkSets,
                              adis1650x::Type adisType);
void createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, HealthTableIF* healthTable,
                            HeaterHandler*& heaterHandler);
void createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets, const char* i2cDev);
void createBpxBatteryComponent(bool enableHkSets, const char* i2cDev);
void createStrComponents(PowerSwitchIF* pwrSwitcher, SdCardManager& sdcMan);
void createSolarArrayDeploymentComponents(PowerSwitchIF& pwrSwitcher, GpioIF& gpioIF);
void createSyrlinksComponents(PowerSwitchIF* pwrSwitcher);
void createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF& pwrSwitcher);
void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF* pwrSwitcher);
ReturnValue_t createCcsdsIpComponentsWrapper(CcsdsComponentArgs& args);
ReturnValue_t createCcsdsComponents(CcsdsComponentArgs& args);
ReturnValue_t readFirmwareVersion();
void createMiscComponents();

void createTestComponents(LinuxLibgpioIF* gpioComIF);
void createPlI2cResetGpio(LinuxLibgpioIF* gpioComIF);

void testAcsBrdAss(AcsBoardAssembly* assAss);

};  // namespace ObjectFactory

#endif /* BSP_Q7S_OBJECTFACTORY_H_ */