#include "rule_match_editor.hpp"
#include "block/block.hpp"
#include "document/idocument.hpp"
#include "rules/rule_match.hpp"
#include "widgets/net_button.hpp"
#include "widgets/multi_net_button.hpp"
#include "widgets/net_class_button.hpp"


namespace horizon {
RuleMatchEditor::RuleMatchEditor(RuleMatch &ma, class IDocument &c)
    : Gtk::Box(Gtk::ORIENTATION_VERTICAL, 4), match(ma), core(c)
{
    combo_mode = Gtk::manage(new Gtk::ComboBoxText());
    combo_mode->append(std::to_string(static_cast<int>(RuleMatch::Mode::ALL)), "All");
    combo_mode->append(std::to_string(static_cast<int>(RuleMatch::Mode::NET)), "Single net");
    combo_mode->append(std::to_string(static_cast<int>(RuleMatch::Mode::NETS)), "Multiple nets");
    combo_mode->append(std::to_string(static_cast<int>(RuleMatch::Mode::NET_CLASS)), "Net class");
    combo_mode->append(std::to_string(static_cast<int>(RuleMatch::Mode::NET_NAME_REGEX)), "Net name (regex)");
    combo_mode->append(std::to_string(static_cast<int>(RuleMatch::Mode::NET_CLASS_REGEX)), "Net class (regex)");
    combo_mode->set_active_id(std::to_string(static_cast<int>(match.mode)));
    combo_mode->signal_changed().connect([this] {
        match.mode = static_cast<RuleMatch::Mode>(std::stoi(combo_mode->get_active_id()));
        sel_stack->set_visible_child(combo_mode->get_active_id());
        s_signal_updated.emit();
    });

    pack_start(*combo_mode, false, false, 0);
    combo_mode->show();

    sel_stack = Gtk::manage(new Gtk::Stack());
    sel_stack->set_homogeneous(true);
    Block &block = *core.get_top_block();

    net_button = Gtk::manage(new NetButton(block));
    net_button->set_no_expand(true);
    net_button->set_net(match.net);
    net_button->signal_changed().connect([this](const UUID &uu) {
        match.net = uu;
        s_signal_updated.emit();
    });
    sel_stack->add(*net_button, std::to_string(static_cast<int>(RuleMatch::Mode::NET)));

    multi_net_button = Gtk::manage(new MultiNetButton(block));
    multi_net_button->set_items(match.nets);
    multi_net_button->signal_changed().connect([this] {
        match.nets = multi_net_button->get_items();
        s_signal_updated.emit();
    });
    sel_stack->add(*multi_net_button, std::to_string(static_cast<int>(RuleMatch::Mode::NETS)));

    net_class_button = Gtk::manage(new NetClassButton(*core.get_top_block()));
    if (!match.net_class) {
        match.net_class = core.get_top_block()->net_class_default->uuid;
    }
    net_class_button->set_net_class(match.net_class);
    net_class_button->signal_net_class_changed().connect([this](const UUID &uu) {
        match.net_class = uu;
        s_signal_updated.emit();
    });
    sel_stack->add(*net_class_button, std::to_string(static_cast<int>(RuleMatch::Mode::NET_CLASS)));

    net_name_regex_entry = Gtk::manage(new Gtk::Entry());
    net_name_regex_entry->set_text(match.net_name_regex);
    net_name_regex_entry->signal_changed().connect([this] {
        match.net_name_regex = net_name_regex_entry->get_text();
        s_signal_updated.emit();
    });
    sel_stack->add(*net_name_regex_entry, std::to_string(static_cast<int>(RuleMatch::Mode::NET_NAME_REGEX)));

    net_class_regex_entry = Gtk::manage(new Gtk::Entry());
    net_class_regex_entry->set_text(match.net_class_regex);
    net_class_regex_entry->signal_changed().connect([this] {
        match.net_class_regex = net_class_regex_entry->get_text();
        s_signal_updated.emit();
    });
    sel_stack->add(*net_class_regex_entry, std::to_string(static_cast<int>(RuleMatch::Mode::NET_CLASS_REGEX)));

    auto *dummy_label = Gtk::manage(new Gtk::Label("matches all nets"));
    sel_stack->add(*dummy_label, std::to_string(static_cast<int>(RuleMatch::Mode::ALL)));

    pack_start(*sel_stack, true, true, 0);
    sel_stack->show_all();

    sel_stack->set_visible_child(std::to_string(static_cast<int>(match.mode)));
}
} // namespace horizon
