#include <fesa/model/domain_builder.hpp>

#include <span>
#include <type_traits>
#include <utility>
#include <gtest/gtest.h>

namespace {

static_assert(std::is_same_v<
              decltype(std::declval<const fesa::Domain&>().nodes()),
              std::span<const fesa::Node>>);
static_assert(std::is_same_v<
              decltype(std::declval<const fesa::Domain&>().node(
                  std::declval<fesa::NodeId>())),
              const fesa::Node&>);

TEST(EntityOrigin, UsesEmptyScopeNamesForFlatMeshEntities) {
    const fesa::EntityOrigin origin{"", "", 17};

    EXPECT_TRUE(origin.part_name.empty());
    EXPECT_TRUE(origin.instance_name.empty());
    EXPECT_EQ(origin.local_label, 17);
}

TEST(EntityOrigin, FindsHierarchicalNodeByCompositeOrigin) {
    const fesa::Node node{
        fesa::NodeId{0},
        fesa::EntityOrigin{"BeamPart", "Beam-1", 101},
        fesa::Vec3{1.0, 2.0, 3.0},
    };
    fesa::DomainBuilder builder;
    builder.add_node(node);
    builder.set_step(fesa::StepDefinition{"Load", {}, {}});
    auto result = std::move(builder).build();
    ASSERT_TRUE(result.domain.has_value());
    const fesa::Domain& domain = *result.domain;

    const fesa::EntityOrigin lookup{"BeamPart", "Beam-1", 101};
    const fesa::Node& found_by_origin = domain.node(lookup);
    const fesa::Node& found_by_id = domain.node(fesa::NodeId{0});

    EXPECT_EQ(&found_by_origin, &domain.nodes().front());
    EXPECT_EQ(&found_by_id, &domain.nodes().front());
    EXPECT_EQ(found_by_origin.origin.part_name, "BeamPart");
    EXPECT_EQ(found_by_origin.origin.instance_name, "Beam-1");
    EXPECT_EQ(found_by_origin.origin.local_label, 101);
}

}  // namespace
