#include "where_used_box.hpp"
#include "pool/ipool.hpp"
#include "util/sqlite.hpp"
#include "common/object_descr.hpp"

namespace horizon {
WhereUsedBox::WhereUsedBox(IPool &p) : Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL, 4), pool(p)
{
    auto *la = Gtk::manage(new Gtk::Label());
    la->set_markup("<b>Where used</b>");
    la->set_xalign(0);
    la->show();
    pack_start(*la, false, false, 0);

    store = Gtk::ListStore::create(list_columns);
    view = Gtk::manage(new Gtk::TreeView(store));
    {
        auto cr = Gtk::manage(new Gtk::CellRendererText());
        auto tvc = Gtk::manage(new Gtk::TreeViewColumn("Type", *cr));
        tvc->set_cell_data_func(*cr, [this](Gtk::CellRenderer *tcr, const Gtk::TreeModel::iterator &it) {
            Gtk::TreeModel::Row row = *it;
            auto mcr = dynamic_cast<Gtk::CellRendererText *>(tcr);
            mcr->property_text() = object_descriptions.at(row[list_columns.type]).name;
        });
        view->append_column(*tvc);
    }
    {
        auto cr = Gtk::manage(new Gtk::CellRendererText());
        cr->property_ellipsize().set_value(Pango::ELLIPSIZE_END);
        auto tvc = Gtk::manage(new Gtk::TreeViewColumn("Name", *cr));
        tvc->add_attribute(cr->property_text(), list_columns.name);
        view->append_column(*tvc);
    }
    view->show();
    auto sc = Gtk::manage(new Gtk::ScrolledWindow());
    sc->set_shadow_type(Gtk::SHADOW_IN);
    sc->set_min_content_height(200);
    sc->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
    sc->add(*view);
    sc->show_all();

    view->signal_row_activated().connect(sigc::mem_fun(*this, &WhereUsedBox::row_activated));
    pack_start(*sc, true, true, 0);
    set_visible(false);
}

void WhereUsedBox::clear()
{
    store->clear();
}

size_t WhereUsedBox::load(ObjectType type, const UUID &uu)
{
    store->clear();
    if (!uu)
        return 0;
    SQLite::Query q(pool.get_db(),
                    "WITH RECURSIVE where_used(typex, uuidx) AS ( SELECT ?, ? UNION "
                    "SELECT type, uuid FROM dependencies, where_used "
                    "WHERE dependencies.dep_type = where_used.typex "
                    "AND dependencies.dep_uuid = where_used.uuidx) "
                    "SELECT where_used.typex, where_used.uuidx, "
                    "(SELECT all_items_view.name FROM all_items_view "
                    "WHERE where_used.typex = all_items_view.type "
                    "AND where_used.uuidx = all_items_view.uuid) "
                    "FROM where_used");
    q.bind(1, type);
    q.bind(2, uu);
    q.step(); // drop first one
    size_t count = 0;
    while (q.step()) {
        auto it_type = q.get<ObjectType>(0);
        UUID uuid = q.get<std::string>(1);
        std::string name = q.get<std::string>(2);

        Gtk::TreeModel::Row row;
        row = *store->append();
        row[list_columns.type] = it_type;
        row[list_columns.uuid] = uuid;
        row[list_columns.name] = name;
        count++;
    }
    return count;
}

void WhereUsedBox::row_activated(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *column)
{
    auto it = store->get_iter(path);
    if (it) {
        Gtk::TreeModel::Row row = *it;
        s_signal_goto.emit(row[list_columns.type], row[list_columns.uuid]);
    }
}

ItemSet WhereUsedBox::get_items() const
{
    ItemSet r;
    for (const auto &it : store->children()) {
        Gtk::TreeModel::Row row = *it;
        r.emplace(row[list_columns.type], row[list_columns.uuid]);
    }
    return r;
}

} // namespace horizon
