#include <gtest/gtest.h>
#include <type_traits>
#include <utility>
#include "renderive/base/node/Node.hpp"
struct Multiway_Node_Test_Owner {};
struct Multiway_Node_Test_Tag {};
using Multiway_Node_Test_Type = Multiway_Node<Multiway_Node_Test_Owner, Multiway_Node_Test_Tag>;
static_assert(Multiway_Node_Type<Multiway_Node_Test_Type, Multiway_Node_Test_Owner, Multiway_Node_Test_Tag>);
static_assert(!std::same_as<Multiway_Node<Multiway_Node_Test_Owner>, Multiway_Node_Test_Type>);
static_assert(std::same_as<decltype(std::declval<const Multiway_Node_Test_Type&>().child(0)), const Multiway_Node_Test_Type&>);
TEST(multiway_node_test, reparents_child_and_preserves_order) {
    Multiway_Node_Test_Owner first_owner;
    Multiway_Node_Test_Owner second_owner;
    Multiway_Node_Test_Owner third_owner;
    Multiway_Node_Test_Type root;
    Multiway_Node_Test_Type first(&first_owner);
    Multiway_Node_Test_Type second(&second_owner);
    Multiway_Node_Test_Type third(&third_owner);
    root.append_child(first);
    root.append_child(second);
    first.append_child(third);
    EXPECT_EQ(root.child_count(), 2);
    EXPECT_EQ(&first.child(0), &third);
    EXPECT_EQ(third.parent(), &first);
    second.append_child(third);
    EXPECT_TRUE(first.children_empty());
    EXPECT_EQ(third.parent(), &second);
}
TEST(multiway_node_test, rejects_cycles) {
    Multiway_Node_Test_Type root;
    Multiway_Node_Test_Type child;
    root.append_child(child);
    EXPECT_THROW(child.append_child(root), std::invalid_argument);
}
TEST(multiway_node_test, reorders_existing_child_without_invalid_iterator) {
    Multiway_Node_Test_Type root;
    Multiway_Node_Test_Type first;
    Multiway_Node_Test_Type second;
    root.append_child(first);
    root.append_child(second);
    root.append_child(first);
    EXPECT_EQ(root.child_count(), 2);
    EXPECT_EQ(&root.child(0), &second);
    EXPECT_EQ(&root.child(1), &first);
    root.insert_child(0, first);
    EXPECT_EQ(&root.child(0), &first);
    EXPECT_EQ(&root.child(1), &second);
}
TEST(multiway_node_test, rejects_child_index_past_end) {
    Multiway_Node_Test_Type root;
    Multiway_Node_Test_Type child;
    EXPECT_THROW(root.insert_child(1, child), std::out_of_range);
}
