#include "VirtualChannelWithQueue.h"

#include "OBSWConfig.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serviceinterface/ServiceInterfaceStream.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
#include "mission/com/CcsdsIpCoreHandler.h"

VirtualChannelWithQueue::VirtualChannelWithQueue(object_id_t objectId, uint8_t vcId,
                                                 const char* vcName, PtmeIF& ptme,
                                                 const std::atomic_bool& linkStateProvider,
                                                 StorageManagerIF& tmStore, uint32_t tmQueueDepth)
    : VirtualChannel(objectId, vcId, vcName, ptme, linkStateProvider), tmStore(tmStore) {
  auto mqArgs = MqArgs(getObjectId(), reinterpret_cast<void*>(getVcid()));
  tmQueue = QueueFactory::instance()->createMessageQueue(
      tmQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}

const char* VirtualChannelWithQueue::getName() const { return VirtualChannel::getName(); }

ReturnValue_t VirtualChannelWithQueue::handleNextTm(bool performWriteOp) {
  TmTcMessage message;
  ReturnValue_t result = tmQueue->receiveMessage(&message);
  if (result == MessageQueueIF::EMPTY) {
    return result;
  }
  store_address_t storeId = message.getStorageId();
  const uint8_t* data = nullptr;
  size_t size = 0;
  result = tmStore.getData(storeId, &data, &size);
  if (result != returnvalue::OK) {
    sif::warning << "VirtualChannel::performOperation: Failed to read data from TM store"
                 << std::endl;
    tmStore.deleteData(storeId);
    return result;
  }

  if (performWriteOp) {
    result = write(data, size);
  }
  // Try delete in any case, ignore failures (which should not happen), it is more important to
  // propagate write errors.
  tmStore.deleteData(storeId);
  return result;
}

MessageQueueId_t VirtualChannelWithQueue::getReportReceptionQueue(uint8_t virtualChannel) const {
  return tmQueue->getId();
}