#ifndef EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66

#if defined(_MSC_VER) ||                                            \
    (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
     (__GNUC__ >= 4))  // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif

#include <string>

namespace YODA_YAML {
enum EMITTER_MANIP {
  // general manipulators
  Auto,
  TagByKind,
  Newline,

  // output character set
  EmitNonAscii,
  EscapeNonAscii,
  EscapeAsJson,

  // string manipulators
  // Auto, // duplicate
  SingleQuoted,
  DoubleQuoted,
  Literal,

  // null manipulators
  LowerNull,
  UpperNull,
  CamelNull,
  TildeNull,

  // bool manipulators
  YesNoBool,      // yes, no
  TrueFalseBool,  // true, false
  OnOffBool,      // on, off
  UpperCase,      // TRUE, N
  LowerCase,      // f, yes
  CamelCase,      // No, Off
  LongBool,       // yes, On
  ShortBool,      // y, t

  // int manipulators
  Dec,
  Hex,
  Oct,

  // document manipulators
  BeginDoc,
  EndDoc,

  // sequence manipulators
  BeginSeq,
  EndSeq,
  Flow,
  Block,

  // map manipulators
  BeginMap,
  EndMap,
  Key,
  Value,
  // Flow, // duplicate
  // Block, // duplicate
  // Auto, // duplicate
  LongKey
};

struct _Indent {
  _Indent(int value_) : value(value_) {}
  int value;
};

inline _Indent Indent(int value) { return _Indent(value); }

struct _Alias {
  _Alias(const std::string& content_) : content(content_) {}
  std::string content;
};

inline _Alias Alias(const std::string& content) { return _Alias(content); }

struct _Anchor {
  _Anchor(const std::string& content_) : content(content_) {}
  std::string content;
};

inline _Anchor Anchor(const std::string& content) { return _Anchor(content); }

struct _Tag {
  struct Type {
    enum value { Verbatim, PrimaryHandle, NamedHandle };
  };

  explicit _Tag(const std::string& prefix_, const std::string& content_,
                Type::value type_)
      : prefix(prefix_), content(content_), type(type_) {}
  std::string prefix;
  std::string content;
  Type::value type;
};

inline _Tag VerbatimTag(const std::string& content) {
  return _Tag("", content, _Tag::Type::Verbatim);
}

inline _Tag LocalTag(const std::string& content) {
  return _Tag("", content, _Tag::Type::PrimaryHandle);
}

inline _Tag LocalTag(const std::string& prefix, const std::string content) {
  return _Tag(prefix, content, _Tag::Type::NamedHandle);
}

inline _Tag SecondaryTag(const std::string& content) {
  return _Tag("", content, _Tag::Type::NamedHandle);
}

struct _Comment {
  _Comment(const std::string& content_) : content(content_) {}
  std::string content;
};

inline _Comment Comment(const std::string& content) { return _Comment(content); }

struct _Precision {
  _Precision(int floatPrecision_, int doublePrecision_)
      : floatPrecision(floatPrecision_), doublePrecision(doublePrecision_) {}

  int floatPrecision;
  int doublePrecision;
};

inline _Precision FloatPrecision(int n) { return _Precision(n, -1); }

inline _Precision DoublePrecision(int n) { return _Precision(-1, n); }

inline _Precision Precision(int n) { return _Precision(n, n); }
}

#endif  // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
