#include <cassert>
#include <sstream>

#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/emittermanip.h"
#include "yaml-cpp/null.h"

namespace YAML {
struct Mark;
}  // namespace YAML

namespace {
std::string ToString(YAML::anchor_t anchor) {
  std::stringstream stream;
  stream << anchor;
  return stream.str();
}
}  // namespace

namespace YAML {
EmitFromEvents::EmitFromEvents(Emitter& emitter)
    : m_emitter(emitter), m_stateStack{} {}

void EmitFromEvents::OnDocumentStart(const Mark&) {}

void EmitFromEvents::OnDocumentEnd() {}

void EmitFromEvents::OnNull(const Mark&, anchor_t anchor) {
  BeginNode();
  EmitProps("", anchor);
  m_emitter << Null;
}

void EmitFromEvents::OnAlias(const Mark&, anchor_t anchor) {
  BeginNode();
  m_emitter << Alias(ToString(anchor));
}

void EmitFromEvents::OnScalar(const Mark&, const std::string& tag,
                              anchor_t anchor, const std::string& value) {
  BeginNode();
  EmitProps(tag, anchor);
  m_emitter << value;
}

void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag,
                                     anchor_t anchor,
                                     EmitterStyle::value style) {
  BeginNode();
  EmitProps(tag, anchor);
  switch (style) {
    case EmitterStyle::Block:
      m_emitter << Block;
      break;
    case EmitterStyle::Flow:
      m_emitter << Flow;
      break;
    default:
      break;
  }
  // Restore the global settings to eliminate the override from node style
  m_emitter.RestoreGlobalModifiedSettings();
  m_emitter << BeginSeq;
  m_stateStack.push(State::WaitingForSequenceEntry);
}

void EmitFromEvents::OnSequenceEnd() {
  m_emitter << EndSeq;
  assert(m_stateStack.top() == State::WaitingForSequenceEntry);
  m_stateStack.pop();
}

void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag,
                                anchor_t anchor, EmitterStyle::value style) {
  BeginNode();
  EmitProps(tag, anchor);
  switch (style) {
    case EmitterStyle::Block:
      m_emitter << Block;
      break;
    case EmitterStyle::Flow:
      m_emitter << Flow;
      break;
    default:
      break;
  }
  // Restore the global settings to eliminate the override from node style
  m_emitter.RestoreGlobalModifiedSettings();
  m_emitter << BeginMap;
  m_stateStack.push(State::WaitingForKey);
}

void EmitFromEvents::OnMapEnd() {
  m_emitter << EndMap;
  assert(m_stateStack.top() == State::WaitingForKey);
  m_stateStack.pop();
}

void EmitFromEvents::BeginNode() {
  if (m_stateStack.empty())
    return;

  switch (m_stateStack.top()) {
    case State::WaitingForKey:
      m_emitter << Key;
      m_stateStack.top() = State::WaitingForValue;
      break;
    case State::WaitingForValue:
      m_emitter << Value;
      m_stateStack.top() = State::WaitingForKey;
      break;
    default:
      break;
  }
}

void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
  if (!tag.empty() && tag != "?" && tag != "!")
    m_emitter << VerbatimTag(tag);
  if (anchor)
    m_emitter << Anchor(ToString(anchor));
}
}  // namespace YAML
