#include <algorithm>
#include <cstdio>
#include <sstream>

#include "collectionstack.h"  // IWYU pragma: keep
#include "scanner.h"
#include "singledocparser.h"
#include "tag.h"
#include "token.h"
#include "yaml-cpp/depthguard.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
#include "yaml-cpp/mark.h"
#include "yaml-cpp/null.h"

namespace YAML {
SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
    : m_scanner(scanner),
      m_directives(directives),
      m_pCollectionStack(new CollectionStack),
      m_anchors{},
      m_curAnchor(0) {}

SingleDocParser::~SingleDocParser() = default;

// HandleDocument
// . Handles the next document
// . Throws a ParserException on error.
void SingleDocParser::HandleDocument(EventHandler& eventHandler) {
  assert(!m_scanner.empty());  // guaranteed that there are tokens
  assert(!m_curAnchor);

  eventHandler.OnDocumentStart(m_scanner.peek().mark);

  // eat doc start
  if (m_scanner.peek().type == Token::DOC_START)
    m_scanner.pop();

  // recurse!
  HandleNode(eventHandler);

  eventHandler.OnDocumentEnd();

  // and finally eat any doc ends we see
  while (!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
    m_scanner.pop();
}

void SingleDocParser::HandleNode(EventHandler& eventHandler) {
  DepthGuard<500> depthguard(depth, m_scanner.mark(), ErrorMsg::BAD_FILE);

  // an empty node *is* a possibility
  if (m_scanner.empty()) {
    eventHandler.OnNull(m_scanner.mark(), NullAnchor);
    return;
  }

  // save location
  Mark mark = m_scanner.peek().mark;

  // special case: a value node by itself must be a map, with no header
  if (m_scanner.peek().type == Token::VALUE) {
    eventHandler.OnMapStart(mark, "?", NullAnchor, EmitterStyle::Default);
    HandleMap(eventHandler);
    eventHandler.OnMapEnd();
    return;
  }

  // special case: an alias node
  if (m_scanner.peek().type == Token::ALIAS) {
    eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value));
    m_scanner.pop();
    return;
  }

  std::string tag;
  std::string anchor_name;
  anchor_t anchor;
  ParseProperties(tag, anchor, anchor_name);

  if (!anchor_name.empty())
    eventHandler.OnAnchor(mark, anchor_name);

  // after parsing properties, an empty node is again a possibility
  if (m_scanner.empty()) {
    eventHandler.OnNull(mark, anchor);
    return;
  }

  const Token& token = m_scanner.peek();

  // add non-specific tags
  if (tag.empty())
    tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");

  if (token.type == Token::PLAIN_SCALAR
      && tag.compare("?") == 0 && IsNullString(token.value)) {
    eventHandler.OnNull(mark, anchor);
    m_scanner.pop();
    return;
  }

  // now split based on what kind of node we should be
  switch (token.type) {
    case Token::PLAIN_SCALAR:
    case Token::NON_PLAIN_SCALAR:
      eventHandler.OnScalar(mark, tag, anchor, token.value);
      m_scanner.pop();
      return;
    case Token::FLOW_SEQ_START:
      eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Flow);
      HandleSequence(eventHandler);
      eventHandler.OnSequenceEnd();
      return;
    case Token::BLOCK_SEQ_START:
      eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Block);
      HandleSequence(eventHandler);
      eventHandler.OnSequenceEnd();
      return;
    case Token::FLOW_MAP_START:
      eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow);
      HandleMap(eventHandler);
      eventHandler.OnMapEnd();
      return;
    case Token::BLOCK_MAP_START:
      eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Block);
      HandleMap(eventHandler);
      eventHandler.OnMapEnd();
      return;
    case Token::KEY:
      // compact maps can only go in a flow sequence
      if (m_pCollectionStack->GetCurCollectionType() ==
          CollectionType::FlowSeq) {
        eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow);
        HandleMap(eventHandler);
        eventHandler.OnMapEnd();
        return;
      }
      break;
    default:
      break;
  }

  if (tag == "?")
    eventHandler.OnNull(mark, anchor);
  else
    eventHandler.OnScalar(mark, tag, anchor, "");
}

void SingleDocParser::HandleSequence(EventHandler& eventHandler) {
  // split based on start token
  switch (m_scanner.peek().type) {
    case Token::BLOCK_SEQ_START:
      HandleBlockSequence(eventHandler);
      break;
    case Token::FLOW_SEQ_START:
      HandleFlowSequence(eventHandler);
      break;
    default:
      break;
  }
}

void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
  // eat start token
  m_scanner.pop();
  m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);

  while (true) {
    if (m_scanner.empty())
      throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);

    Token token = m_scanner.peek();
    if (token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
      throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);

    m_scanner.pop();
    if (token.type == Token::BLOCK_SEQ_END)
      break;

    // check for null
    if (!m_scanner.empty()) {
      const Token& nextToken = m_scanner.peek();
      if (nextToken.type == Token::BLOCK_ENTRY ||
          nextToken.type == Token::BLOCK_SEQ_END) {
        eventHandler.OnNull(nextToken.mark, NullAnchor);
        continue;
      }
    }

    HandleNode(eventHandler);
  }

  m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
}

void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler) {
  // eat start token
  m_scanner.pop();
  m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);

  while (true) {
    if (m_scanner.empty())
      throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);

    // first check for end
    if (m_scanner.peek().type == Token::FLOW_SEQ_END) {
      m_scanner.pop();
      break;
    }

    // then read the node
    HandleNode(eventHandler);

    if (m_scanner.empty())
      throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);

    // now eat the separator (or could be a sequence end, which we ignore - but
    // if it's neither, then it's a bad node)
    Token& token = m_scanner.peek();
    if (token.type == Token::FLOW_ENTRY)
      m_scanner.pop();
    else if (token.type != Token::FLOW_SEQ_END)
      throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
  }

  m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
}

void SingleDocParser::HandleMap(EventHandler& eventHandler) {
  // split based on start token
  switch (m_scanner.peek().type) {
    case Token::BLOCK_MAP_START:
      HandleBlockMap(eventHandler);
      break;
    case Token::FLOW_MAP_START:
      HandleFlowMap(eventHandler);
      break;
    case Token::KEY:
      HandleCompactMap(eventHandler);
      break;
    case Token::VALUE:
      HandleCompactMapWithNoKey(eventHandler);
      break;
    default:
      break;
  }
}

void SingleDocParser::HandleBlockMap(EventHandler& eventHandler) {
  // eat start token
  m_scanner.pop();
  m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);

  while (true) {
    if (m_scanner.empty())
      throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);

    Token token = m_scanner.peek();
    if (token.type != Token::KEY && token.type != Token::VALUE &&
        token.type != Token::BLOCK_MAP_END)
      throw ParserException(token.mark, ErrorMsg::END_OF_MAP);

    if (token.type == Token::BLOCK_MAP_END) {
      m_scanner.pop();
      break;
    }

    // grab key (if non-null)
    if (token.type == Token::KEY) {
      m_scanner.pop();
      HandleNode(eventHandler);
    } else {
      eventHandler.OnNull(token.mark, NullAnchor);
    }

    // now grab value (optional)
    if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
      m_scanner.pop();
      HandleNode(eventHandler);
    } else {
      eventHandler.OnNull(token.mark, NullAnchor);
    }
  }

  m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
}

void SingleDocParser::HandleFlowMap(EventHandler& eventHandler) {
  // eat start token
  m_scanner.pop();
  m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);

  while (true) {
    if (m_scanner.empty())
      throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);

    Token& token = m_scanner.peek();
    const Mark mark = token.mark;
    // first check for end
    if (token.type == Token::FLOW_MAP_END) {
      m_scanner.pop();
      break;
    }

    // grab key (if non-null)
    if (token.type == Token::KEY) {
      m_scanner.pop();
      HandleNode(eventHandler);
    } else {
      eventHandler.OnNull(mark, NullAnchor);
    }

    // now grab value (optional)
    if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
      m_scanner.pop();
      HandleNode(eventHandler);
    } else {
      eventHandler.OnNull(mark, NullAnchor);
    }

    if (m_scanner.empty())
      throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);

    // now eat the separator (or could be a map end, which we ignore - but if
    // it's neither, then it's a bad node)
    Token& nextToken = m_scanner.peek();
    if (nextToken.type == Token::FLOW_ENTRY)
      m_scanner.pop();
    else if (nextToken.type != Token::FLOW_MAP_END)
      throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
  }

  m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
}

// . Single "key: value" pair in a flow sequence
void SingleDocParser::HandleCompactMap(EventHandler& eventHandler) {
  m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);

  // grab key
  Mark mark = m_scanner.peek().mark;
  m_scanner.pop();
  HandleNode(eventHandler);

  // now grab value (optional)
  if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
    m_scanner.pop();
    HandleNode(eventHandler);
  } else {
    eventHandler.OnNull(mark, NullAnchor);
  }

  m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
}

// . Single ": value" pair in a flow sequence
void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler) {
  m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);

  // null key
  eventHandler.OnNull(m_scanner.peek().mark, NullAnchor);

  // grab value
  m_scanner.pop();
  HandleNode(eventHandler);

  m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
}

// ParseProperties
// . Grabs any tag or anchor tokens and deals with them.
void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor,
                                      std::string& anchor_name) {
  tag.clear();
  anchor_name.clear();
  anchor = NullAnchor;

  while (true) {
    if (m_scanner.empty())
      return;

    switch (m_scanner.peek().type) {
      case Token::TAG:
        ParseTag(tag);
        break;
      case Token::ANCHOR:
        ParseAnchor(anchor, anchor_name);
        break;
      default:
        return;
    }
  }
}

void SingleDocParser::ParseTag(std::string& tag) {
  Token& token = m_scanner.peek();
  if (!tag.empty())
    throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);

  Tag tagInfo(token);
  tag = tagInfo.Translate(m_directives);
  m_scanner.pop();
}

void SingleDocParser::ParseAnchor(anchor_t& anchor, std::string& anchor_name) {
  Token& token = m_scanner.peek();
  if (anchor)
    throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);

  anchor_name = token.value;
  anchor = RegisterAnchor(token.value);
  m_scanner.pop();
}

anchor_t SingleDocParser::RegisterAnchor(const std::string& name) {
  if (name.empty())
    return NullAnchor;

  return m_anchors[name] = ++m_curAnchor;
}

anchor_t SingleDocParser::LookupAnchor(const Mark& mark,
                                       const std::string& name) const {
  auto it = m_anchors.find(name);
  if (it == m_anchors.end())
    throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);

  return it->second;
}
}  // namespace YAML
