#include <cstdio>
#include <sstream>

#include "directives.h"  // IWYU pragma: keep
#include "scanner.h"     // IWYU pragma: keep
#include "singledocparser.h"
#include "token.h"
#include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
#include "yaml-cpp/parser.h"

namespace YAML {
class EventHandler;

Parser::Parser() : m_pScanner{}, m_pDirectives{} {}

Parser::Parser(std::istream& in) : Parser() { Load(in); }

Parser::~Parser() = default;

Parser::operator bool() const { return m_pScanner && !m_pScanner->empty(); }

void Parser::Load(std::istream& in) {
  m_pScanner.reset(new Scanner(in));
  m_pDirectives.reset(new Directives);
}

bool Parser::HandleNextDocument(EventHandler& eventHandler) {
  if (!m_pScanner)
    return false;

  ParseDirectives();
  if (m_pScanner->empty()) {
    return false;
  }

  SingleDocParser sdp(*m_pScanner, *m_pDirectives);
  sdp.HandleDocument(eventHandler);
  return true;
}

void Parser::ParseDirectives() {
  bool readDirective = false;

  while (!m_pScanner->empty()) {
    Token& token = m_pScanner->peek();
    if (token.type != Token::DIRECTIVE) {
      break;
    }

    // we keep the directives from the last document if none are specified;
    // but if any directives are specific, then we reset them
    if (!readDirective) {
      m_pDirectives.reset(new Directives);
    }

    readDirective = true;
    HandleDirective(token);
    m_pScanner->pop();
  }
}

void Parser::HandleDirective(const Token& token) {
  if (token.value == "YAML") {
    HandleYamlDirective(token);
  } else if (token.value == "TAG") {
    HandleTagDirective(token);
  }
}

void Parser::HandleYamlDirective(const Token& token) {
  if (token.params.size() != 1) {
    throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
  }

  if (!m_pDirectives->version.isDefault) {
    throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
  }

  std::stringstream str(token.params[0]);
  str.imbue(std::locale::classic());
  str >> m_pDirectives->version.major;
  str.get();
  str >> m_pDirectives->version.minor;
  if (!str || str.peek() != EOF) {
    throw ParserException(
        token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
  }

  if (m_pDirectives->version.major > 1) {
    throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
  }

  m_pDirectives->version.isDefault = false;
  // TODO: warning on major == 1, minor > 2?
}

void Parser::HandleTagDirective(const Token& token) {
  if (token.params.size() != 2)
    throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);

  const std::string& handle = token.params[0];
  const std::string& prefix = token.params[1];
  if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end()) {
    throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
  }

  m_pDirectives->tags[handle] = prefix;
}

void Parser::PrintTokens(std::ostream& out) {
  if (!m_pScanner) {
    return;
  }

  while (!m_pScanner->empty()) {
    out << m_pScanner->peek() << "\n";
    m_pScanner->pop();
  }
}
}  // namespace YAML
