#ifndef MISSION_TMTC_LIVETMTASK_H_
#define MISSION_TMTC_LIVETMTASK_H_

#include <fsfw/modes/HasModesIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/subsystem/ModeTreeChildIF.h>
#include <fsfw/subsystem/ModeTreeConnectionIF.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/timemanager/Countdown.h>
#include <mission/com/VirtualChannelWithQueue.h>
#include <mission/tmtc/CfdpTmFunnel.h>
#include <mission/tmtc/PusTmFunnel.h>

#include <cstdint>

#include "eive/definitions.h"

static constexpr bool DEBUG_CFDP_TO_LIVE_TM_TASK = false;

class LiveTmTask : public SystemObject,
                   public HasModesIF,
                   public ExecutableObjectIF,
                   public ModeTreeChildIF,
                   public ModeTreeConnectionIF {
 public:
  LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel,
             VirtualChannel& channel, const std::atomic_bool& ptmeLocked,
             uint32_t regularTmQueueDepth, uint32_t cfdpQueueDepth);

  MessageQueueId_t getNormalLiveQueueId() const;
  MessageQueueId_t getCfdpLiveQueueId() const;
  ReturnValue_t performOperation(uint8_t opCode) override;
  ReturnValue_t initialize() override;
  ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;

 private:
  MessageQueueIF* requestQueue;
  MessageQueueIF* cfdpTmQueue;
  MessageQueueIF* regularTmQueue;
  StorageManagerIF* tmStore = nullptr;
  ModeHelper modeHelper;
  Mode_t mode = HasModesIF::MODE_OFF;
  Countdown tmFunnelCd = Countdown(100);
  PusTmFunnel& pusFunnel;
  CfdpTmFunnel& cfdpFunnel;
  VirtualChannel& channel;
  const std::atomic_bool& ptmeLocked;
  bool throttlePeriodOngoing = false;
  bool channelIsBusy = false;

  void readCommandQueue(void);

  ReturnValue_t handleRegularTmQueue();
  ReturnValue_t handleCfdpTmQueue();
  ReturnValue_t handleGenericTmQueue(MessageQueueIF& queue, bool isCfdp);

  MessageQueueId_t getCommandQueue() const override;

  void getMode(Mode_t* mode, Submode_t* submode) override;

  void cfdpBackpressureHandling();

  ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
                                 uint32_t* msToReachTheMode) override;

  void startTransition(Mode_t mode, Submode_t submode) override;

  void announceMode(bool recursive) override;
  void throttleCfdp();
  void releaseCfdp();
  void updateBusyFlag();

  object_id_t getObjectId() const override;
  const HasHealthIF* getOptHealthIF() const override;
  const HasModesIF& getModeIF() const override;
  ModeTreeChildIF& getModeTreeChildIF() override;
};

#endif /* MISSION_TMTC_LIVETMTASK_H_ */