#include <bsp_q7s/callbacks/q7sGpioCallbacks.h>
#include <devices/gpioIds.h>
#include <fsfw/storagemanager/LocalPool.h>
#include <fsfw/storagemanager/PoolManager.h>
#include <mission/power/gsDefs.h>
#include <mission/system/EiveSystem.h>

#include "OBSWConfig.h"
#include "bsp_q7s/core/CoreController.h"
#include "bsp_q7s/core/ObjectFactory.h"
#include "busConf.h"
#include "devConf.h"
#include "eive/objects.h"
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
#include "linux/ObjectFactory.h"
#include "linux/callbacks/gpioCallbacks.h"
#include "mission/genericFactory.h"
#include "mission/system/systemTree.h"
#include "mission/tmtc/tmFilters.h"

void ObjectFactory::produce(void* args) {
  ObjectFactory::setStatics();
  HealthTableIF* healthTable = nullptr;
  PusTmFunnel* pusFunnel = nullptr;
  CfdpTmFunnel* cfdpFunnel = nullptr;
  StorageManagerIF* ipcStore = nullptr;
  StorageManagerIF* tmStore = nullptr;

  bool enableHkSets = false;
#if OBSW_ENABLE_PERIODIC_HK == 1
  enableHkSets = true;
#endif

  PersistentTmStores stores;
  ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
                                       *SdCardManager::instance(), &ipcStore, &tmStore, stores,
                                       200);

  LinuxLibgpioIF* gpioComIF = nullptr;
  SerialComIF* uartComIF = nullptr;
  SpiComIF* spiMainComIF = nullptr;
  I2cComIF* i2cComIF = nullptr;
  PowerSwitchIF* pwrSwitcher = nullptr;
  createCommunicationInterfaces(&gpioComIF, &uartComIF, &spiMainComIF, &i2cComIF);
  /* Adding gpios for chip select decoding to the gpioComIf */
  q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF);
  gpioCallbacks::disableAllDecoder(gpioComIF);

  new CoreController(objects::CORE_CONTROLLER, enableHkSets);
  createPcduComponents(gpioComIF, &pwrSwitcher, enableHkSets);
  satsystem::EIVE_SYSTEM.setI2cRecoveryParams(pwrSwitcher);

  auto* stackHandler = new Stack5VHandler(*pwrSwitcher);

#if OBSW_ADD_RAD_SENSORS == 1
  createRadSensorComponent(gpioComIF, *stackHandler);
#endif
#if OBSW_ADD_SUN_SENSORS == 1
  createSunSensorComponents(gpioComIF, spiMainComIF, *pwrSwitcher, q7s::SPI_DEFAULT_DEV, true);
#endif

#if OBSW_ADD_ACS_BOARD == 1
  createAcsBoardComponents(*spiMainComIF, gpioComIF, uartComIF, *pwrSwitcher, true,
                           adis1650x::Type::ADIS16505);
#endif
  HeaterHandler* heaterHandler;
  createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);
#if OBSW_ADD_TMP_DEVICES == 1
  createTmpComponents();
#endif
  createSolarArrayDeploymentComponents(*pwrSwitcher, *gpioComIF);
  createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler);
#if OBSW_ADD_SYRLINKS == 1
  createSyrlinksComponents(pwrSwitcher);
#endif /* OBSW_ADD_SYRLINKS == 1 */
  createRtdComponents(q7s::SPI_DEFAULT_DEV, gpioComIF, pwrSwitcher, spiMainComIF);
  createPayloadComponents(gpioComIF, *pwrSwitcher);

#if OBSW_ADD_MGT == 1
  createImtqComponents(pwrSwitcher, enableHkSets);
#endif
  createReactionWheelComponents(gpioComIF, pwrSwitcher);

#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
  createBpxBatteryComponent(enableHkSets);
#endif

#if OBSW_ADD_STAR_TRACKER == 1
  createStrComponents(pwrSwitcher);
#endif /* OBSW_ADD_STAR_TRACKER == 1 */

#if OBSW_ADD_CCSDS_IP_CORES == 1
  CcsdsIpCoreHandler* ipCoreHandler = nullptr;
  CcsdsComponentArgs ccsdsArgs(*gpioComIF, *ipcStore, *tmStore, stores, *pusFunnel, *cfdpFunnel,
                               &ipCoreHandler);
  createCcsdsComponents(ccsdsArgs);
#if OBSW_TM_TO_PTME == 1
  if (ccsdsArgs.liveDestination != nullptr) {
    pusFunnel->addLiveDestination("VC0 LIVE TM", *ccsdsArgs.liveDestination, 0);
    cfdpFunnel->addLiveDestination("VC0 LIVE TM", *ccsdsArgs.liveDestination, 0);
  }
#endif
#endif /* OBSW_ADD_CCSDS_IP_CORES == 1 */

#if OBSW_ADD_SCEX_DEVICE == 1
  createScexComponents(q7s::UART_SCEX_DEV, pwrSwitcher, *SdCardManager::instance(), false,
                       power::Switches::PDU1_CH5_SOLAR_CELL_EXP_5V);
#endif
  /* Test Task */
#if OBSW_ADD_TEST_CODE == 1
  createTestComponents(gpioComIF);
#endif /* OBSW_ADD_TEST_CODE == 1 */

  createMiscComponents();
  createThermalController(*heaterHandler);
  createAcsController(true, enableHkSets);
  satsystem::init();
}