#ifndef BSP_Q7S_CORE_NVMPARAMS_NVMPARAMIF_H_
#define BSP_Q7S_CORE_NVMPARAMS_NVMPARAMIF_H_

#include <filesystem>
#include <nlohmann/json.hpp>
#include <string>

#include "fsfw/returnvalues/HasReturnvaluesIF.h"

class NVMParameterBase : public HasReturnvaluesIF {
 public:
  virtual ~NVMParameterBase() {}

  NVMParameterBase(std::string fullName);

  bool getJsonFileExists();

  /**
   * Returns RETURN_OK on successfull read and HasFileSystemIF::FILE_DOES_NOT_EXIST if
   * file does not exist yet.
   * @return
   */
  virtual ReturnValue_t readJsonFile();

  virtual ReturnValue_t writeJsonFile();

  void setFullName(std::string fullName);
  std::string getFullName() const;

  template <typename T>
  ReturnValue_t insertValue(std::string key, T value);

  template <typename T>
  ReturnValue_t setValue(std::string key, T value);

  template <typename T>
  ReturnValue_t getValue(std::string key, T& value) const;

  void printKeys() const;
  void print() const;

 private:
  static const uint8_t INTERFACE_ID = CLASS_ID::NVM_PARAM_BASE;

  //! [EXPORT] : [COMMENT] Specified key does not exist in json file
  static const ReturnValue_t KEY_NOT_EXISTS = MAKE_RETURN_CODE(0xA0);

  nlohmann::json json;
  std::vector<std::string> keys;
  std::string fullName;
};

template <typename T>
inline ReturnValue_t NVMParameterBase::insertValue(std::string key, T value) {
  // Check whether key already exists. If it does not, insert it
  if (std::find(keys.begin(), keys.end(), key) == keys.end()) {
    keys.push_back(key);
  }
  json[key] = value;
  return HasReturnvaluesIF::RETURN_OK;
}

template <typename T>
inline ReturnValue_t NVMParameterBase::setValue(std::string key, T value) {
  json[key] = value;
  return HasReturnvaluesIF::RETURN_OK;
}

template <typename T>
inline ReturnValue_t NVMParameterBase::getValue(std::string key, T& value) const {
  if (!json.contains(key)) {
    return KEY_NOT_EXISTS;
  }
  value = json[key];
  return RETURN_OK;
}

#endif /* BSP_Q7S_CORE_NVMPARAMS_NVMPARAMIF_H_ */