#include <algorithm>
#include <cassert>
#include <iterator>
#include <sstream>

#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/node/detail/memory.h"
#include "yaml-cpp/node/detail/node.h"  // IWYU pragma: keep
#include "yaml-cpp/node/detail/node_data.h"
#include "yaml-cpp/node/detail/node_iterator.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/type.h"

namespace YAML {
namespace detail {
std::atomic<size_t> node::m_amount{0};

const std::string& node_data::empty_scalar() {
  static const std::string svalue;
  return svalue;
}

node_data::node_data()
    : m_isDefined(false),
      m_mark(Mark::null_mark()),
      m_type(NodeType::Null),
      m_tag{},
      m_style(EmitterStyle::Default),
      m_scalar{},
      m_sequence{},
      m_seqSize(0),
      m_map{},
      m_undefinedPairs{} {}

void node_data::mark_defined() {
  if (m_type == NodeType::Undefined)
    m_type = NodeType::Null;
  m_isDefined = true;
}

void node_data::set_mark(const Mark& mark) { m_mark = mark; }

void node_data::set_type(NodeType::value type) {
  if (type == NodeType::Undefined) {
    m_type = type;
    m_isDefined = false;
    return;
  }

  m_isDefined = true;
  if (type == m_type)
    return;

  m_type = type;

  switch (m_type) {
    case NodeType::Null:
      break;
    case NodeType::Scalar:
      m_scalar.clear();
      break;
    case NodeType::Sequence:
      reset_sequence();
      break;
    case NodeType::Map:
      reset_map();
      break;
    case NodeType::Undefined:
      assert(false);
      break;
  }
}

void node_data::set_tag(const std::string& tag) { m_tag = tag; }

void node_data::set_style(EmitterStyle::value style) { m_style = style; }

void node_data::set_null() {
  m_isDefined = true;
  m_type = NodeType::Null;
}

void node_data::set_scalar(const std::string& scalar) {
  m_isDefined = true;
  m_type = NodeType::Scalar;
  m_scalar = scalar;
}

// size/iterator
std::size_t node_data::size() const {
  if (!m_isDefined)
    return 0;

  switch (m_type) {
    case NodeType::Sequence:
      compute_seq_size();
      return m_seqSize;
    case NodeType::Map:
      compute_map_size();
      return m_map.size() - m_undefinedPairs.size();
    default:
      return 0;
  }
  return 0;
}

void node_data::compute_seq_size() const {
  while (m_seqSize < m_sequence.size() && m_sequence[m_seqSize]->is_defined())
    m_seqSize++;
}

void node_data::compute_map_size() const {
  auto it = m_undefinedPairs.begin();
  while (it != m_undefinedPairs.end()) {
    auto jt = std::next(it);
    if (it->first->is_defined() && it->second->is_defined())
      m_undefinedPairs.erase(it);
    it = jt;
  }
}

const_node_iterator node_data::begin() const {
  if (!m_isDefined)
    return {};

  switch (m_type) {
    case NodeType::Sequence:
      return const_node_iterator(m_sequence.begin());
    case NodeType::Map:
      return const_node_iterator(m_map.begin(), m_map.end());
    default:
      return {};
  }
}

node_iterator node_data::begin() {
  if (!m_isDefined)
    return {};

  switch (m_type) {
    case NodeType::Sequence:
      return node_iterator(m_sequence.begin());
    case NodeType::Map:
      return node_iterator(m_map.begin(), m_map.end());
    default:
      return {};
  }
}

const_node_iterator node_data::end() const {
  if (!m_isDefined)
    return {};

  switch (m_type) {
    case NodeType::Sequence:
      return const_node_iterator(m_sequence.end());
    case NodeType::Map:
      return const_node_iterator(m_map.end(), m_map.end());
    default:
      return {};
  }
}

node_iterator node_data::end() {
  if (!m_isDefined)
    return {};

  switch (m_type) {
    case NodeType::Sequence:
      return node_iterator(m_sequence.end());
    case NodeType::Map:
      return node_iterator(m_map.end(), m_map.end());
    default:
      return {};
  }
}

// sequence
void node_data::push_back(node& node,
                          const shared_memory_holder& /* pMemory */) {
  if (m_type == NodeType::Undefined || m_type == NodeType::Null) {
    m_type = NodeType::Sequence;
    reset_sequence();
  }

  if (m_type != NodeType::Sequence)
    throw BadPushback();

  m_sequence.push_back(&node);
}

void node_data::insert(node& key, node& value,
                       const shared_memory_holder& pMemory) {
  switch (m_type) {
    case NodeType::Map:
      break;
    case NodeType::Undefined:
    case NodeType::Null:
    case NodeType::Sequence:
      convert_to_map(pMemory);
      break;
    case NodeType::Scalar:
      throw BadSubscript(m_mark, key);
  }

  insert_map_pair(key, value);
}

// indexing
node* node_data::get(node& key,
                     const shared_memory_holder& /* pMemory */) const {
  if (m_type != NodeType::Map) {
    return nullptr;
  }

  for (const auto& it : m_map) {
    if (it.first->is(key))
      return it.second;
  }

  return nullptr;
}

node& node_data::get(node& key, const shared_memory_holder& pMemory) {
  switch (m_type) {
    case NodeType::Map:
      break;
    case NodeType::Undefined:
    case NodeType::Null:
    case NodeType::Sequence:
      convert_to_map(pMemory);
      break;
    case NodeType::Scalar:
      throw BadSubscript(m_mark, key);
  }

  for (const auto& it : m_map) {
    if (it.first->is(key))
      return *it.second;
  }

  node& value = pMemory->create_node();
  insert_map_pair(key, value);
  return value;
}

bool node_data::remove(node& key, const shared_memory_holder& /* pMemory */) {
  if (m_type != NodeType::Map)
    return false;

  for (auto it = m_undefinedPairs.begin(); it != m_undefinedPairs.end();) {
    auto jt = std::next(it);
    if (it->first->is(key))
      m_undefinedPairs.erase(it);
    it = jt;
  }

  auto it =
      std::find_if(m_map.begin(), m_map.end(),
                   [&](std::pair<YAML::detail::node*, YAML::detail::node*> j) {
                     return (j.first->is(key));
                   });

  if (it != m_map.end()) {
    m_map.erase(it);
    return true;
  }

  return false;
}

void node_data::reset_sequence() {
  m_sequence.clear();
  m_seqSize = 0;
}

void node_data::reset_map() {
  m_map.clear();
  m_undefinedPairs.clear();
}

void node_data::insert_map_pair(node& key, node& value) {
  m_map.emplace_back(&key, &value);

  if (!key.is_defined() || !value.is_defined())
    m_undefinedPairs.emplace_back(&key, &value);
}

void node_data::convert_to_map(const shared_memory_holder& pMemory) {
  switch (m_type) {
    case NodeType::Undefined:
    case NodeType::Null:
      reset_map();
      m_type = NodeType::Map;
      break;
    case NodeType::Sequence:
      convert_sequence_to_map(pMemory);
      break;
    case NodeType::Map:
      break;
    case NodeType::Scalar:
      assert(false);
      break;
  }
}

void node_data::convert_sequence_to_map(const shared_memory_holder& pMemory) {
  assert(m_type == NodeType::Sequence);

  reset_map();
  for (std::size_t i = 0; i < m_sequence.size(); i++) {
    std::stringstream stream;
    stream << i;

    node& key = pMemory->create_node();
    key.set_scalar(stream.str());
    insert_map_pair(key, *m_sequence[i]);
  }

  reset_sequence();
  m_type = NodeType::Map;
}
}  // namespace detail
}  // namespace YAML
