#ifndef CF_TYPE_REGISTRY_H
#define CF_TYPE_REGISTRY_H

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

#include "cf_step_abi.h"

namespace cf {

struct ResolvedDatatype {
  std::string id;
  std::string canonical_port_type_iri;
  std::string canonical_parameter_type_iri;
  CfStorageType storage_type = CF_STORAGE_OPAQUE;
};

class TypeRegistry {
 public:
  bool resolve_port_type(const std::string& datatype, ResolvedDatatype& out) const;
  bool resolve_parameter_type(const std::string& datatype, ResolvedDatatype& out) const;
  bool are_port_types_compatible(const std::string& output_datatype, const std::string& input_datatype) const;

 private:
  struct Entry {
    std::string id;
    std::string canonical_port_type_iri;
    std::string canonical_parameter_type_iri;
    CfStorageType storage_type = CF_STORAGE_OPAQUE;
    std::vector<std::string> compatible_input_ids;
  };

  friend bool load_default_type_registry(TypeRegistry& out, std::string& error);

  std::vector<Entry> entries_;
  std::unordered_map<std::string, size_t> port_alias_to_index_;
  std::unordered_map<std::string, size_t> parameter_alias_to_index_;
  std::unordered_map<std::string, size_t> id_to_index_;

  bool resolve_from_index(size_t index, ResolvedDatatype& out) const;
};

bool load_default_type_registry(TypeRegistry& out, std::string& error);

}  // namespace cf

#endif
