#include "pw/scene/entity.hpp"
#include "pw/scene/scene.hpp"

#include "pw/core/debug.hpp"

namespace pw {

namespace detail {


// entity identiy is hidden

struct identity {
    identity() = default;
    identity(const std::string& name) : name(name) {}
    identity(const identity&) = default;

    bool enabled = true;
    std::string name = "";
    std::vector<u_int32_t> tags = {};
    std::vector<uint32_t> layers = {};
};

}

entity::entity(scene &s,const std::string& name)
    : _registry(s._registry)
    , _entity(s._registry ? _registry->create() : entt::null)
{
    if (s._registry) {
        this->add_component<detail::identity>(name);
    }
}

bool entity::add_child(entity &child)
{
    // not mixing scenes (yet)
    if (child._registry != this->_registry) {
        debug::e() << "Cannot mix entities from different scenes";
        return false;
    }

    // TODO: check circular dependencies

    // declare child relationship
    auto& c = this->get_or_create_component<children>();
    c.entities.push_back(child._entity);

    // declare parent
    auto& p_r = child.get_or_create_component<parent>();
    p_r.entity = _entity;

    return true;
}

bool entity::remove_child(entity& child)
{
    // not mixing scenes (yet)
    if (child._registry != this->_registry) {
        debug::e() << "Cannot mix entities from different scenes";
        return false;
    }

    // both need to have a relationship component
    if (child.has_component<parent>() &&
            this->has_component<children>())
    {
        // we need to check if the child is related to the parent
        auto r_p = child.get_component<parent>();
        if (r_p.entity == _entity)
        {
            // now go ahead delete parent
            r_p.entity = entt::null;

            // now remove all children
            auto& c = this->get_component<children>();
            c.entities.erase(std::remove(c.entities.begin(),c.entities.end(),child._entity));

            // flag success
            return true;
        }
    }
    return false;
}


size_t entity::child_count() const
{
    return this->has_component<children>() ?
                get_component<children>().entities.size() :
                0;
}


void entity::set_name(const std::string& n)
{
    auto &ident = get_or_create_component<detail::identity>();
    ident.name = n;
}

std::string entity::name()
{
    auto &ident = get_or_create_component<detail::identity>();
    return ident.name;
}



entity::~entity()
{
    this->destroy();
}

void entity::destroy()
{
    _registry->destroy(_entity);
}

}

