#ifndef MISSION_TMTC_TMSTORETASKBASE_H_
#define MISSION_TMTC_TMSTORETASKBASE_H_

#include <fsfw/timemanager/Countdown.h>
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
#include <mission/tmtc/VirtualChannel.h>

/**
 * Generic class which composes a Virtual Channel and a persistent TM stores. This allows dumping
 * the TM store into the virtual channel directly.
 */
class TmStoreTaskBase : public SystemObject {
 public:
  struct DumpContext {
    DumpContext(Event eventIfDone, Event eventIfCancelled)
        : eventIfDone(eventIfDone), eventIfCancelled(eventIfCancelled) {}
    void reset() {
      numberOfDumpedPackets = 0;
      dumpedBytes = 0;
      vcBusyDuringDump = false;
      packetWasDumped = false;
      bytesDumpedAtLastDelay = 0;
      ptmeBusyCounter = 0;
    }
    const Event eventIfDone;
    const Event eventIfCancelled;
    size_t numberOfDumpedPackets = 0;
    size_t bytesDumpedAtLastDelay = 0;
    size_t dumpedBytes = 0;
    uint32_t ptmeBusyCounter = 0;
    bool packetWasDumped = false;
    bool vcBusyDuringDump = false;
  };

  TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, VirtualChannel& channel,
                  SdCardMountedIF& sdcMan);

 protected:
  StorageManagerIF& ipcStore;
  Countdown sdCardCheckCd = Countdown(800);
  // 20 minutes are allowed as maximum dump time.
  Countdown cancelDumpCd = Countdown(60 * 20 * 1000);
  // If the TM sink is busy for 1 minute for whatever reason, cancel the dump.
  Countdown tmSinkBusyCd = Countdown(60 * 1000);
  VirtualChannel& channel;
  bool storesInitialized = false;
  bool fileHasSwapped = false;
  SdCardMountedIF& sdcMan;

  void cancelDump(DumpContext& ctx, PersistentTmStore& store, bool isTxOn);
  /**
   *
   * Handling for one store. Returns if anything was done.
   * @param store
   * @return
   */
  bool handleOneStore(PersistentTmStoreWithTmQueue& store, DumpContext& dumpContext);

  ReturnValue_t handleOneDump(PersistentTmStoreWithTmQueue& store, DumpContext& dumpContext,
                              bool& dumpPerformed);

  /**
   * Occasionally check whether SD card is okay to be used. If not, poll whether it is ready to
   * be used again and re-initialize stores. Returns whether store is okay to be used.
   */
  bool cyclicStoreCheck();

  virtual bool initStoresIfPossible() = 0;
};

#endif /* MISSION_TMTC_TMSTORETASKBASE_H_ */