#include "Service15TmStorage.h"

#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>

#include "eive/objects.h"
#include "fsfw/tmstorage/TmStoreMessage.h"

using namespace returnvalue;

Service15TmStorage::Service15TmStorage(object_id_t objectId, uint16_t apid,
                                       uint8_t numParallelCommands, uint16_t commandTimeoutSecs,
                                       size_t queueDepth)
    : CommandingServiceBase(objectId, apid, "PUS Service 15", 15, numParallelCommands,
                            commandTimeoutSecs, queueDepth) {}

ReturnValue_t Service15TmStorage::isValidSubservice(uint8_t subservice) {
  switch (subservice) {
    case (Subservices::DELETE_UP_TO):
    case (Subservices::START_BY_TIME_RANGE_RETRIEVAL): {
      return OK;
    }
    default: {
      return FAILED;
    }
  }
}

ReturnValue_t Service15TmStorage::getMessageQueueAndObject(uint8_t subservice,
                                                           const uint8_t *tcData, size_t tcDataLen,
                                                           MessageQueueId_t *id,
                                                           object_id_t *objectId) {
  if (tcDataLen < 4) {
    return CommandingServiceBase::INVALID_TC;
  }
  SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::NETWORK);
  auto *frontendIF = ObjectManager::instance()->get<TmStoreFrontendSimpleIF>(*objectId);
  if (frontendIF == nullptr) {
    return CommandingServiceBase::INVALID_OBJECT;
  }
  *id = frontendIF->getCommandQueue();
  return OK;
}

ReturnValue_t Service15TmStorage::prepareCommand(CommandMessage *message, uint8_t subservice,
                                                 const uint8_t *tcData, size_t tcDataLen,
                                                 uint32_t *state, object_id_t objectId) {
  if (subservice == Subservices::START_BY_TIME_RANGE_RETRIEVAL) {
    // TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
    //       to time reading and reply handling
    if (tcDataLen != 12) {
      return INVALID_TC;
    }
    store_address_t storeId;
    ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
    if (result != OK) {
      return result;
    }
    // Store timestamps
    TmStoreMessage::setDownlinkContentTimeMessage(message, storeId);
    return CommandingServiceBase::EXECUTION_COMPLETE;
  } else if (subservice == Subservices::DELETE_UP_TO) {
    // TODO: Hardcoded to UNIX timestamps.. Should allow arbitrary timestamp and let receiver
    //       to time reading and reply handling
    if (tcDataLen != 8) {
      return INVALID_TC;
    }
    store_address_t storeId;
    ReturnValue_t result = ipcStore->addData(&storeId, tcData + 4, tcDataLen - 4);
    if (result != OK) {
      return result;
    }
    // Store timestamps
    TmStoreMessage::setDeleteContentTimeMessage(message, storeId);
    return CommandingServiceBase::EXECUTION_COMPLETE;
  }
  return OK;
}

ReturnValue_t Service15TmStorage::handleReply(const CommandMessage *reply,
                                              Command_t previousCommand, uint32_t *state,
                                              CommandMessage *optionalNextCommand,
                                              object_id_t objectId, bool *isStep) {
  return OK;
}