#ifndef CF_JSONLD_LOADER_H
#define CF_JSONLD_LOADER_H

#include <optional>
#include <string>
#include <unordered_map>
#include <vector>

#include "cf_step_abi.h"

namespace cf {

enum class ParallelismModel {
  kNone = 0,
  kOmp,
  kTbb,
  kBlas,
  kMkl,
  kCuda,
  kExternal,
  kUnknown,
};

struct StepParallelism {
  ParallelismModel model = ParallelismModel::kNone;
  std::optional<int> preferred_threads;
  std::optional<int> max_threads;
  std::optional<bool> deterministic;
  std::optional<int> schema_version;
};

struct ParameterDef {
  std::string iri;
  std::string name;
  CfStorageType storage_type;
  std::string type_iri;
  std::string default_json;
  bool has_default = false;
  bool required = false;
  std::optional<double> min_value;
  std::optional<double> max_value;
  std::vector<std::string> allowed_values;
};

struct PortDef {
  std::string iri;
  std::string key;
  CfStorageType storage_type;
  std::string type_iri;
  bool is_multi = false;
};

struct StepDef {
  std::string iri;
  StepParallelism parallelism;
  std::vector<ParameterDef> parameters;
  std::vector<PortDef> inputs;
  std::vector<PortDef> outputs;
};

struct StepCatalog {
  std::unordered_map<std::string, StepDef> steps;
};

struct JsonLdContext {
  std::unordered_map<std::string, std::string> prefixes;
};

StepCatalog load_step_catalog(const std::vector<std::string>& step_files, std::string& error);

std::string expand_iri(const JsonLdContext& ctx, const std::string& value);

}  // namespace cf

#endif
