#include "ObjectFactory.h"

#include <fsfw/power/DummyPowerSwitcher.h>
#include <fsfw/tmtcservices/CommandingServiceBase.h>
#include <fsfw/tmtcservices/PusServiceBase.h>
#include <mission/controller/ThermalController.h>
#include <mission/core/GenericFactory.h>
#include <mission/tmtc/TmFunnelHandler.h>
#include <objects/systemObjectList.h>

#include "../mission/utility/DummySdCardManager.h"
#include "OBSWConfig.h"
#include "fsfw/platform.h"
#include "fsfw_tests/integration/task/TestTask.h"

#if OBSW_ADD_TMTC_UDP_SERVER == 1
#include "fsfw/osal/common/UdpTcPollingTask.h"
#include "fsfw/osal/common/UdpTmTcBridge.h"
#endif
#if OBSW_ADD_TMTC_TCP_SERVER == 1
#include "fsfw/osal/common/TcpTmTcBridge.h"
#include "fsfw/osal/common/TcpTmTcServer.h"
#endif

#if OBSW_ADD_TEST_CODE == 1
#include <test/testtasks/TestTask.h>
#endif

#include <dummies/AcuDummy.h>
#include <dummies/CoreControllerDummy.h>

#include "dummies/helpers.h"

#ifdef PLATFORM_UNIX
#include <fsfw_hal/linux/serial/SerialComIF.h>
#include <fsfw_hal/linux/serial/SerialCookie.h>

#include "devices/gpioIds.h"
#include "fsfw_hal/linux/gpio/Gpio.h"
#include "linux/devices/ploc/PlocMPSoCHandler.h"
#include "linux/devices/ploc/PlocMPSoCHelper.h"
#include "linux/devices/ploc/PlocSupervisorHandler.h"
#include "linux/devices/ploc/PlocSupvUartMan.h"
#include "test/gpio/DummyGpioIF.h"
#endif

void Factory::setStaticFrameworkObjectIds() {
  PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_PACKET_DISTRIBUTOR;
  PusServiceBase::PACKET_DESTINATION = objects::PUS_TM_FUNNEL;

  CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR;
  CommandingServiceBase::defaultPacketDestination = objects::PUS_TM_FUNNEL;

  VerificationReporter::DEFAULT_RECEIVER = objects::PUS_SERVICE_1_VERIFICATION;
}

void ObjectFactory::produce(void* args) {
  Factory::setStaticFrameworkObjectIds();
  PusTmFunnel* pusFunnel;
  CfdpTmFunnel* cfdpFunnel;
  StorageManagerIF* tmStore;
  StorageManagerIF* ipcStore;
  PersistentTmStores persistentStores;
  auto sdcMan = new DummySdCardManager("/tmp");
  ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel, *sdcMan, &ipcStore,
                                       &tmStore, persistentStores);

  auto* dummyGpioIF = new DummyGpioIF();
  auto* dummySwitcher = new DummyPowerSwitcher(objects::PCDU_HANDLER, 18, 0);
#ifdef PLATFORM_UNIX
  new SerialComIF(objects::UART_COM_IF);
#if OBSW_ADD_PLOC_MPSOC == 1
  std::string mpscoDev = "";
  auto mpsocCookie = new UartCookie(objects::PLOC_MPSOC_HANDLER, mpscoDev, uart::PLOC_MPSOC_BAUD,
                                    mpsoc::MAX_REPLY_SIZE, UartModes::NON_CANONICAL);
  mpsocCookie->setNoFixedSizeReply();
  auto plocMpsocHelper = new PlocMPSoCHelper(objects::PLOC_MPSOC_HELPER);
  new PlocMPSoCHandler(objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, mpsocCookie,
                       plocMpsocHelper, Gpio(gpioIds::ENABLE_MPSOC_UART, dummyGpioIF),
                       objects::PLOC_SUPERVISOR_HANDLER);
#endif /* OBSW_ADD_PLOC_MPSOC == 1 */
#if OBSW_ADD_PLOC_SUPERVISOR == 1
  std::string plocSupvString = "/dev/ploc_supv";
  auto supervisorCookie =
      new SerialCookie(objects::PLOC_SUPERVISOR_HANDLER, plocSupvString, uart::PLOC_SUPV_BAUD,
                       supv::MAX_PACKET_SIZE * 20, UartModes::NON_CANONICAL);
  supervisorCookie->setNoFixedSizeReply();
  auto supvHelper = new PlocSupvUartManager(objects::PLOC_SUPERVISOR_HELPER);
  new PlocSupervisorHandler(objects::PLOC_SUPERVISOR_HANDLER, supervisorCookie,
                            Gpio(gpioIds::ENABLE_SUPV_UART, dummyGpioIF), pcdu::PDU1_CH6_PLOC_12V,
                            *supvHelper);
#endif /* OBSW_ADD_PLOC_SUPERVISOR == 1 */
#endif

  dummy::DummyCfg cfg;
  dummy::createDummies(cfg, *dummySwitcher, dummyGpioIF);

  HeaterHandler* heaterHandler = nullptr;
  // new ThermalController(objects::THERMAL_CONTROLLER);
  ObjectFactory::createGenericHeaterComponents(*dummyGpioIF, *dummySwitcher, heaterHandler);
  if (heaterHandler == nullptr) {
    sif::error << "HeaterHandler could not be created" << std::endl;
  } else {
    ObjectFactory::createThermalController(*heaterHandler);
  }
  new TestTask(objects::TEST_TASK);
}