#include "get_cmd.h"

USING_YOSYS_NAMESPACE

void GetCmd::help() {
    //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
    log("\n");
    log("   get_%ss [-quiet] [-filter filter_expression] "
        "<%s_selection> \n",
        TypeName().c_str(), TypeName().c_str());
    log("\n");
    log("Get matching %ss\n", TypeName().c_str());
    log("\n");
    log("Print the output to stdout too. This is useful when all Yosys "
        "is "
        "executed.\n");
    log("\n");
    log("    -filter\n");
    log("        Name and value of attribute to be taken into "
        "account.\n");
    log("        e.g. -filter { attr == \"true\" }\n");
    log("\n");
    log("    -quiet\n");
    log("        Don't print the result of the execution to stdout.\n");
    log("\n");
    log("    <selection_pattern>\n");
    log("        Selection of %s names. Default are all %ss in the "
        "design.\n",
        TypeName().c_str(), TypeName().c_str());
    log("\n");
}

void GetCmd::ExecuteSelection(RTLIL::Design* design, const CommandArgs& args) {
    std::vector<std::string> selection_args;
    // Add name of top module to selection string
    std::transform(args.selection_objects.begin(), args.selection_objects.end(),
                   std::back_inserter(selection_args),
                   [&](const std::string& obj) {
	               return RTLIL::unescape_id(design->top_module()->name) +
	                      "/" + SelectionType() + ":" + obj;
                   });
    extra_args(selection_args, 0, design);
    if (design->selected_modules().empty()) {
	if (!args.is_quiet) {
	    log_warning("Specified %s not found in design\n",
	                TypeName().c_str());
	}
    }
}

void GetCmd::PackToTcl(const SelectionObjects& objects) {
    Tcl_Obj* tcl_result;
    if (objects.size() == 1) {
	tcl_result = Tcl_NewStringObj(objects.at(0).c_str(), -1);
    } else {
	tcl_result = Tcl_NewListObj(0, NULL);
	for (const auto& object : objects) {
	    Tcl_Obj* value_obj = Tcl_NewStringObj(object.c_str(), -1);
	    Tcl_ListObjAppendElement(yosys_get_tcl_interp(), tcl_result,
	                             value_obj);
	}
    }
    Tcl_SetObjResult(yosys_get_tcl_interp(), tcl_result);
}

GetCmd::CommandArgs GetCmd::ParseCommand(const std::vector<std::string>& args) {
    CommandArgs parsed_args{.filters = Filters(),
                            .is_quiet = false,
                            .selection_objects = SelectionObjects()};
    size_t argidx(0);
    for (argidx = 1; argidx < args.size(); argidx++) {
	std::string arg = args[argidx];
	if (arg == "-quiet") {
	    parsed_args.is_quiet = true;
	    continue;
	}

	if (arg == "-filter" and argidx + 1 < args.size()) {
	    std::string filter_arg = args[++argidx];

	    // Remove spaces
	    filter_arg.erase(
	        std::remove_if(filter_arg.begin(), filter_arg.end(), isspace),
	        filter_arg.end());

	    // Parse filters
	    // TODO Add support for multiple condition expression
	    // Currently only a single == is supported
	    std::regex filter_attr_regex("(\\w+\\s?==\\s?\\w+)([(||)(&&)]*)");
	    std::regex_token_iterator<std::string::iterator> regex_end;
	    std::regex_token_iterator<std::string::iterator> matches(
	        filter_arg.begin(), filter_arg.end(), filter_attr_regex, 1);
	    if (matches == regex_end) {
		log_warning(
		    "Currently -filter switch supports only a single "
		    "'equal(==)' condition expression, the rest will be "
		    "ignored\n");
	    }

	    while (matches != regex_end) {
		std::string filter(*matches++);
		auto separator = filter.find("==");
		if (separator == std::string::npos) {
		    log_cmd_error("Incorrect filter expression: %s\n",
		                  args[argidx].c_str());
		}
		parsed_args.filters.emplace_back(filter.substr(0, separator),
		                                 filter.substr(separator + 2));
	    }
	    if (parsed_args.filters.size() > 1) {
		log_warning(
		    "Currently -filter switch supports only a single "
		    "'equal(==)' condition expression, the rest will be "
		    "ignored\n");
	    }
	    continue;
	}

	if (arg.size() > 0 and arg[0] == '-') {
	    log_cmd_error("Unknown option %s.\n", arg.c_str());
	}

	break;
    }
    std::copy(args.begin() + argidx, args.end(),
              std::back_inserter(parsed_args.selection_objects));
    return parsed_args;
}

void GetCmd::execute(std::vector<std::string> args, RTLIL::Design* design) {
    if (design->top_module() == nullptr) {
	log_cmd_error("No top module detected\n");
    }

    CommandArgs parsed_args(ParseCommand(args));
    ExecuteSelection(design, parsed_args);
    PackToTcl(ExtractSelection(design, parsed_args));
}
