#ifndef SQLTREENODE_HPP
#define SQLTREENODE_HPP

#include "../sqltreenode/sqltreenode.h"

template <typename DataType>
// zero in recordIdentifier - nonexistent record
inline SqlTreeNode<DataType>::SqlTreeNode()
    : recordIdentifier(0), parent(nullptr) {}

// template<typename DataType>
// SqlTreeNode<DataType>::SqlTreeNode(SqlTreeNode &&other) : SqlTreeNode() {
//   other.parent = this;
//   nestedNodes.push_back(std::move(other));
// }

template <typename DataType>
inline SqlTreeNode<DataType>::SqlTreeNode(SqlTreeNode *_parent,
                                          size_t _recordIdentifier,
                                          const DataType &_data)
    : parent(_parent), recordIdentifier(_recordIdentifier), data(_data) {}

template <typename DataType>
inline SqlTreeNode<DataType>::SqlTreeNode(SqlTreeNode *_parent,
                                          size_t _recordIdentifier,
                                          DataType &&_data)
    : parent(_parent), recordIdentifier(_recordIdentifier), data(_data) {}

template <typename DataType>
template <typename T, typename>
SqlTreeNode<DataType> *
SqlTreeNode<DataType>::createFront(size_t recordIdentifier,
                                   T &&newSqlTreeNodeData) {
  auto *newNode = new struct SqlTreeNode(this, recordIdentifier,
                                         std::forward<T>(newSqlTreeNodeData));
  nestedNodes.emplace_back(newNode);
  return newNode;
}
template <typename DataType>
template <typename T, typename>
SqlTreeNode<DataType> *
SqlTreeNode<DataType>::createBack(size_t recordIdentifier,
                                  T &&newSqlTreeNodeData) {
  auto *newNode = new struct SqlTreeNode(this, recordIdentifier,
                                         std::forward<T>(newSqlTreeNodeData));
  // passing on the inheritance to a descendant
  auto &nestedNodesNewNode = newNode->nestedNodes;
  std::copy(std::make_move_iterator(nestedNodes.begin()),
            std::make_move_iterator(nestedNodes.end()),
            std::inserter(nestedNodesNewNode, nestedNodesNewNode.end()));
  // making a descendant
  nestedNodes.emplace_back(newNode);
  return newNode;
}

template <typename DataType>
inline void SqlTreeNode<DataType>::remove(SqlTreeNode *node) {
  auto it = std::find_if(
      nestedNodes.begin(), nestedNodes.end(),
      [&](std::unique_ptr<struct SqlTreeNode> &p) { return p.get() == node; });
  nestedNodes.erase(it);
}

#endif // SQLTREENODE_HPP
