#pragma once

#include "xtr/doc/RSFormDoc.h"
#include "xtr/doc/RSModelDoc.h"

namespace xtr::doc {

//! RS editing Facade
class RSFacade {
private:
  bool isModel{ false };
  RSFormDoc* schemaDoc{};
  RSModelDoc* modelDoc{};

public:
  explicit RSFacade(RSFormDoc& doc) noexcept
    : isModel{ false }, schemaDoc{ &doc } {} // NOLINT(modernize-use-default-member-init)
  explicit RSFacade(RSModelDoc& doc) noexcept
    : isModel{ true }, modelDoc{ &doc } {}

  RSFacade() noexcept = default;
  RSFacade(const RSFacade&) noexcept = default;
  RSFacade& operator=(const RSFacade&) noexcept = default;
  RSFacade(RSFacade&&) noexcept = default;
  RSFacade& operator=(RSFacade&&) noexcept = default;

public:
  [[nodiscard]] bool IsModel() const noexcept { return isModel; }
  [[nodiscard]] SelectableDoc& Document() noexcept;

  [[nodiscard]] const ccl::semantic::RSCore& Core() const noexcept;
  [[nodiscard]] ccl::semantic::RSForm& EditSchema() noexcept;
  [[nodiscard]] const ccl::semantic::RSForm& Schema() const noexcept;
  [[nodiscard]] ccl::semantic::RSModel& EditModel() noexcept;
  [[nodiscard]] const ccl::semantic::RSModel& Model() const noexcept;

  [[nodiscard]] const ccl::semantic::Thesaurus& Texts() const noexcept;
  [[nodiscard]] const ccl::semantic::Schema& RSLang() const noexcept;
  [[nodiscard]] const ccl::semantic::CstList& List() const noexcept;

  [[nodiscard]] bool Contains(EntityUID entity) const;
  [[nodiscard]] const ccl::semantic::RSConcept& GetRS(EntityUID entity) const;
  [[nodiscard]] const ccl::semantic::TextConcept& GetText(EntityUID entity) const;
  [[nodiscard]] const ccl::semantic::ParsingInfo& GetParse(EntityUID entity) const;

  void SetComment(const std::string& newComment);

  ccl::EntityUID Emplace(ccl::semantic::CstType type, const std::string& definition = {});
  ccl::VectorOfEntities InsertCopy(const std::vector<ccl::semantic::ConceptRecord>& input);

  bool MoveBefore(EntityUID what, ccl::semantic::ListIterator iWhere);

  bool SetAliasFor(EntityUID target, const std::string& newName, bool substitue = true);
  bool SetExpressionFor(EntityUID target, const std::string& expression);
  bool SetTermFor(EntityUID target, const std::string& termRef);
  bool SetTermFormFor(EntityUID target, const std::string& termRef, const ccl::lang::Morphology& form);
  bool SetDefinitionFor(EntityUID target, const std::string& textDef);
  bool SetConventionFor(EntityUID target, const std::string& convention);

  void ResetAliases();
};

} // namespace xtr::doc