/*
 * See vpr/SRC/route/build_switchblocks.c for a detailed description of how the new
 * switch block format works and what files are involved.
 *
 *
 * A large chunk of this file is dedicated to helping parse the initial switchblock
 * specificaiton in the XML arch file, providing error checking, etc.
 *
 * Another large chunk of this file is dedicated to parsing the actual formulas
 * specified by the switch block permutation functions into their numeric counterparts.
 */

#include <string.h>
#include <string>
#include <sstream>
#include <vector>
#include <stack>
#include <utility>
#include <algorithm>

#include "vtr_assert.h"
#include "vtr_util.h"

#include "pugixml.hpp"
#include "pugixml_util.hpp"

#include "arch_error.h"

#include "read_xml_util.h"
#include "arch_util.h"
#include "arch_types.h"
#include "physical_types.h"
#include "parse_switchblocks.h"

using pugiutil::ReqOpt;

/**** Function Declarations ****/
/*---- Functions for Parsing Switchblocks from Architecture ----*/

//Load an XML wireconn specification into a t_wireconn_inf
t_wireconn_inf parse_wireconn(pugi::xml_node node, const pugiutil::loc_data& loc_data);

//Process the desired order of a wireconn
static void parse_switchpoint_order(const char* order, SwitchPointOrder& switchpoint_order);

//Process a wireconn defined in the inline style (using attributes)
void parse_wireconn_inline(pugi::xml_node node, const pugiutil::loc_data& loc_data, t_wireconn_inf& wc);

//Process a wireconn defined in the multinode style (more advanced specification)
void parse_wireconn_multinode(pugi::xml_node node, const pugiutil::loc_data& loc_data, t_wireconn_inf& wc);

//Process a <from> or <to> sub-node of a multinode wireconn
t_wire_switchpoints parse_wireconn_from_to_node(pugi::xml_node node, const pugiutil::loc_data& loc_data);

/* parses the wire types specified in the comma-separated 'ch' char array into the vector wire_points_vec.
 * Spaces are trimmed off */
static void parse_comma_separated_wire_types(const char* ch, std::vector<t_wire_switchpoints>& wire_switchpoints);

/* parses the wirepoints specified in ch into the vector wire_points_vec */
static void parse_comma_separated_wire_points(const char* ch, std::vector<t_wire_switchpoints>& wire_switchpoints);

/* Parses the number of connections type */
static void parse_num_conns(std::string num_conns, t_wireconn_inf& wireconn);

/* checks for correctness of a unidir switchblock. */
static void check_unidir_switchblock(const t_switchblock_inf* sb);

/* checks for correctness of a bidir switchblock. */
static void check_bidir_switchblock(const t_permutation_map* permutation_map);

/* checks for correctness of a wireconn segment specification. */
static void check_wireconn(const t_arch* arch, const t_wireconn_inf& wireconn);

/**** Function Definitions ****/

/*---- Functions for Parsing Switchblocks from Architecture ----*/

/* Reads-in the wire connections specified for the switchblock in the xml arch file */
void read_sb_wireconns(const t_arch_switch_inf* /*switches*/, int /*num_switches*/, pugi::xml_node Node, t_switchblock_inf* sb, const pugiutil::loc_data& loc_data) {
    /* Make sure that Node is a switchblock */
    check_node(Node, "switchblock", loc_data);

    int num_wireconns;
    pugi::xml_node SubElem;

    /* count the number of specified wire connections for this SB */
    num_wireconns = count_children(Node, "wireconn", loc_data, ReqOpt::OPTIONAL);
    sb->wireconns.reserve(num_wireconns);

    if (num_wireconns > 0) {
        SubElem = get_first_child(Node, "wireconn", loc_data);
    }
    for (int i = 0; i < num_wireconns; i++) {
        t_wireconn_inf wc = parse_wireconn(SubElem, loc_data);
        sb->wireconns.push_back(wc);
        SubElem = SubElem.next_sibling(SubElem.name());
    }

    return;
}

t_wireconn_inf parse_wireconn(pugi::xml_node node, const pugiutil::loc_data& loc_data) {
    t_wireconn_inf wc;

    size_t num_children = count_children(node, "from", loc_data, ReqOpt::OPTIONAL);
    num_children += count_children(node, "to", loc_data, ReqOpt::OPTIONAL);

    if (num_children == 0) {
        parse_wireconn_inline(node, loc_data, wc);
    } else {
        VTR_ASSERT(num_children > 0);
        parse_wireconn_multinode(node, loc_data, wc);
    }

    return wc;
}

void parse_wireconn_inline(pugi::xml_node node, const pugiutil::loc_data& loc_data, t_wireconn_inf& wc) {
    //Parse an inline wireconn definition, using attributes
    expect_only_attributes(node, {"num_conns", "from_type", "to_type", "from_switchpoint", "to_switchpoint", "from_order", "to_order"}, loc_data);

    /* get the connection style */
    const char* char_prop = get_attribute(node, "num_conns", loc_data).value();
    parse_num_conns(char_prop, wc);

    /* get from type */
    char_prop = get_attribute(node, "from_type", loc_data).value();
    parse_comma_separated_wire_types(char_prop, wc.from_switchpoint_set);

    /* get to type */
    char_prop = get_attribute(node, "to_type", loc_data).value();
    parse_comma_separated_wire_types(char_prop, wc.to_switchpoint_set);

    /* get the source wire point */
    char_prop = get_attribute(node, "from_switchpoint", loc_data).value();
    parse_comma_separated_wire_points(char_prop, wc.from_switchpoint_set);

    /* get the destination wire point */
    char_prop = get_attribute(node, "to_switchpoint", loc_data).value();
    parse_comma_separated_wire_points(char_prop, wc.to_switchpoint_set);

    char_prop = get_attribute(node, "from_order", loc_data, ReqOpt::OPTIONAL).value();
    parse_switchpoint_order(char_prop, wc.from_switchpoint_order);

    char_prop = get_attribute(node, "to_order", loc_data, ReqOpt::OPTIONAL).value();
    parse_switchpoint_order(char_prop, wc.to_switchpoint_order);
}

void parse_wireconn_multinode(pugi::xml_node node, const pugiutil::loc_data& loc_data, t_wireconn_inf& wc) {
    expect_only_children(node, {"from", "to"}, loc_data);

    /* get the connection style */
    const char* char_prop = get_attribute(node, "num_conns", loc_data).value();
    parse_num_conns(char_prop, wc);

    char_prop = get_attribute(node, "from_order", loc_data, ReqOpt::OPTIONAL).value();
    parse_switchpoint_order(char_prop, wc.from_switchpoint_order);

    char_prop = get_attribute(node, "to_order", loc_data, ReqOpt::OPTIONAL).value();
    parse_switchpoint_order(char_prop, wc.to_switchpoint_order);

    size_t num_from_children = count_children(node, "from", loc_data);
    size_t num_to_children = count_children(node, "to", loc_data);

    VTR_ASSERT(num_from_children > 0);
    VTR_ASSERT(num_to_children > 0);

    for (pugi::xml_node child : node.children()) {
        if (child.name() == std::string("from")) {
            t_wire_switchpoints from_switchpoints = parse_wireconn_from_to_node(child, loc_data);
            wc.from_switchpoint_set.push_back(from_switchpoints);
        } else if (child.name() == std::string("to")) {
            t_wire_switchpoints to_switchpoints = parse_wireconn_from_to_node(child, loc_data);
            wc.to_switchpoint_set.push_back(to_switchpoints);
        } else {
            archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "Unrecognized child node '%s' of parent node '%s'",
                           node.name(), child.name());
        }
    }
}

t_wire_switchpoints parse_wireconn_from_to_node(pugi::xml_node node, const pugiutil::loc_data& loc_data) {
    expect_only_attributes(node, {"type", "switchpoint"}, loc_data);

    size_t attribute_count = count_attributes(node, loc_data);

    if (attribute_count != 2) {
        archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "Expected only 2 attributes on node '%s'",
                       node.name());
    }

    t_wire_switchpoints wire_switchpoints;
    wire_switchpoints.segment_name = get_attribute(node, "type", loc_data).value();

    auto points_str = get_attribute(node, "switchpoint", loc_data).value();
    for (const auto& point_str : vtr::split(points_str, ",")) {
        int switchpoint = vtr::atoi(point_str);
        wire_switchpoints.switchpoints.push_back(switchpoint);
    }

    if (wire_switchpoints.switchpoints.empty()) {
        archfpga_throw(loc_data.filename_c_str(), loc_data.line(node), "Empty switchpoint specification",
                       node.name());
    }

    return wire_switchpoints;
}

static void parse_switchpoint_order(const char* order, SwitchPointOrder& switchpoint_order) {
    if (order == std::string("")) {
        switchpoint_order = SwitchPointOrder::SHUFFLED; //Default
    } else if (order == std::string("fixed")) {
        switchpoint_order = SwitchPointOrder::FIXED;
    } else if (order == std::string("shuffled")) {
        switchpoint_order = SwitchPointOrder::SHUFFLED;
    } else {
        archfpga_throw(__FILE__, __LINE__, "Unrecognized switchpoint order '%s'", order);
    }
}

/* parses the wire types specified in the comma-separated 'ch' char array into the vector wire_points_vec.
 * Spaces are trimmed off */
static void parse_comma_separated_wire_types(const char* ch, std::vector<t_wire_switchpoints>& wire_switchpoints) {
    auto types = vtr::split(ch, ",");

    if (types.empty()) {
        archfpga_throw(__FILE__, __LINE__, "parse_comma_separated_wire_types: found empty wireconn wire type entry\n");
    }

    for (const auto& type : types) {
        t_wire_switchpoints wsp;
        wsp.segment_name = type;

        wire_switchpoints.push_back(wsp);
    }
}

/* parses the wirepoints specified in the comma-separated 'ch' char array into the vector wire_points_vec */
static void parse_comma_separated_wire_points(const char* ch, std::vector<t_wire_switchpoints>& wire_switchpoints) {
    auto points = vtr::split(ch, ",");
    if (points.empty()) {
        archfpga_throw(__FILE__, __LINE__, "parse_comma_separated_wire_points: found empty wireconn wire point entry\n");
    }

    for (const auto& point_str : points) {
        int point = vtr::atoi(point_str);

        for (auto& wire_switchpoint : wire_switchpoints) {
            wire_switchpoint.switchpoints.push_back(point);
        }
    }
}

static void parse_num_conns(std::string num_conns, t_wireconn_inf& wireconn) {
    //num_conns is now interpretted as a formula and processed in build_switchblocks
    wireconn.num_conns_formula = num_conns;
}

/* Loads permutation funcs specified under Node into t_switchblock_inf. Node should be
 * <switchfuncs> */
void read_sb_switchfuncs(pugi::xml_node Node, t_switchblock_inf* sb, const pugiutil::loc_data& loc_data) {
    /* Make sure the passed-in is correct */
    check_node(Node, "switchfuncs", loc_data);

    pugi::xml_node SubElem;

    /* get the number of specified permutation functions */
    int num_funcs = count_children(Node, "func", loc_data, ReqOpt::OPTIONAL);

    const char* func_type;
    const char* func_formula;
    std::vector<std::string>* func_ptr;

    /* used to index into permutation map of switchblock */
    SB_Side_Connection conn;

    /* now we iterate through all the specified permutation functions, and
     * load them into the switchblock structure as appropriate */
    if (num_funcs > 0) {
        SubElem = get_first_child(Node, "func", loc_data);
    }
    for (int ifunc = 0; ifunc < num_funcs; ifunc++) {
        /* get function type */
        func_type = get_attribute(SubElem, "type", loc_data).as_string(nullptr);

        /* get function formula */
        func_formula = get_attribute(SubElem, "formula", loc_data).as_string(nullptr);

        /* go through all the possible cases of func_type */
        if (0 == strcmp(func_type, "lt")) {
            conn.set_sides(LEFT, TOP);
        } else if (0 == strcmp(func_type, "lr")) {
            conn.set_sides(LEFT, RIGHT);
        } else if (0 == strcmp(func_type, "lb")) {
            conn.set_sides(LEFT, BOTTOM);
        } else if (0 == strcmp(func_type, "tl")) {
            conn.set_sides(TOP, LEFT);
        } else if (0 == strcmp(func_type, "tb")) {
            conn.set_sides(TOP, BOTTOM);
        } else if (0 == strcmp(func_type, "tr")) {
            conn.set_sides(TOP, RIGHT);
        } else if (0 == strcmp(func_type, "rt")) {
            conn.set_sides(RIGHT, TOP);
        } else if (0 == strcmp(func_type, "rl")) {
            conn.set_sides(RIGHT, LEFT);
        } else if (0 == strcmp(func_type, "rb")) {
            conn.set_sides(RIGHT, BOTTOM);
        } else if (0 == strcmp(func_type, "bl")) {
            conn.set_sides(BOTTOM, LEFT);
        } else if (0 == strcmp(func_type, "bt")) {
            conn.set_sides(BOTTOM, TOP);
        } else if (0 == strcmp(func_type, "br")) {
            conn.set_sides(BOTTOM, RIGHT);
        } else {
            /* unknown permutation function */
            archfpga_throw(__FILE__, __LINE__, "Unknown permutation function specified: %s\n", func_type);
        }
        func_ptr = &(sb->permutation_map[conn]);

        /* Here we load the specified switch function(s) */
        func_ptr->push_back(std::string(func_formula));

        func_ptr = nullptr;
        /* get the next switchblock function */
        SubElem = SubElem.next_sibling(SubElem.name());
    }

    return;
}

/* checks for correctness of switch block read-in from the XML architecture file */
void check_switchblock(const t_switchblock_inf* sb, const t_arch* arch) {
    /* get directionality */
    enum e_directionality directionality = sb->directionality;

    /* Check for errors in the switchblock descriptions */
    if (UNI_DIRECTIONAL == directionality) {
        check_unidir_switchblock(sb);
    } else {
        VTR_ASSERT(BI_DIRECTIONAL == directionality);
        check_bidir_switchblock(&(sb->permutation_map));
    }

    /* check that specified wires exist */
    for (const auto& wireconn : sb->wireconns) {
        check_wireconn(arch, wireconn);
    }

    //TODO:
    /* check that the wire segment directionality matches the specified switch block directionality */
    /* check for duplicate names */
    /* check that specified switches exist */
    /* check that type of switchblock matches type of switch specified */
}

/* checks for correctness of a unidirectional switchblock. hard exit if error found (to be changed to throw later) */
static void check_unidir_switchblock(const t_switchblock_inf* sb) {
    /* Check that the destination wire points are always the starting points (i.e. of wire point 0) */
    for (const t_wireconn_inf& wireconn : sb->wireconns) {
        for (const t_wire_switchpoints& wire_to_points : wireconn.to_switchpoint_set) {
            if (wire_to_points.switchpoints.size() > 1 || wire_to_points.switchpoints[0] != 0) {
                archfpga_throw(__FILE__, __LINE__, "Unidirectional switch blocks are currently only allowed to drive the start points of wire segments\n");
            }
        }
    }
}

/* checks for correctness of a bidirectional switchblock */
static void check_bidir_switchblock(const t_permutation_map* permutation_map) {
    /**** check that if side1->side2 is specified, then side2->side1 is not, as it is implicit ****/

    /* variable used to index into the permutation map */
    SB_Side_Connection conn;

    /* iterate over all combinations of from_side -> to side */
    for (e_side from_side : {TOP, RIGHT, BOTTOM, LEFT}) {
        for (e_side to_side : {TOP, RIGHT, BOTTOM, LEFT}) {
            /* can't connect a switchblock side to itself */
            if (from_side == to_side) {
                continue;
            }

            /* index into permutation map with this variable */
            conn.set_sides(from_side, to_side);

            /* check if a connection between these sides exists */
            t_permutation_map::const_iterator it = (*permutation_map).find(conn);
            if (it != (*permutation_map).end()) {
                /* the two sides are connected */
                /* check if the opposite connection has been specified */
                conn.set_sides(to_side, from_side);
                it = (*permutation_map).find(conn);
                if (it != (*permutation_map).end()) {
                    archfpga_throw(__FILE__, __LINE__, "If a bidirectional switch block specifies a connection from side1->side2, no connection should be specified from side2->side1 as it is implicit.\n");
                }
            }
        }
    }

    return;
}

static void check_wireconn(const t_arch* arch, const t_wireconn_inf& wireconn) {
    for (const t_wire_switchpoints& wire_switchpoints : wireconn.from_switchpoint_set) {
        auto seg_name = wire_switchpoints.segment_name;

        //Make sure the segment exists
        const t_segment_inf* seg_info = find_segment(arch, seg_name);
        if (!seg_info) {
            archfpga_throw(__FILE__, __LINE__, "Failed to find segment '%s' for <wireconn> from type specification\n", seg_name.c_str());
        }

        //Check that the specified switch points are valid
        for (int switchpoint : wire_switchpoints.switchpoints) {
            if (switchpoint < 0) {
                archfpga_throw(__FILE__, __LINE__, "Invalid <wireconn> from_switchpoint '%d' (must be >= 0)\n", switchpoint, seg_name.c_str());
            }
            if (switchpoint >= seg_info->length) {
                archfpga_throw(__FILE__, __LINE__, "Invalid <wireconn> from_switchpoints '%d' (must be < %d)\n", switchpoint, seg_info->length);
            }
            //TODO: check that points correspond to valid sb locations
        }
    }

    for (const t_wire_switchpoints& wire_switchpoints : wireconn.to_switchpoint_set) {
        auto seg_name = wire_switchpoints.segment_name;

        //Make sure the segment exists
        const t_segment_inf* seg_info = find_segment(arch, seg_name);
        if (!seg_info) {
            archfpga_throw(__FILE__, __LINE__, "Failed to find segment '%s' for <wireconn> to type specification\n", seg_name.c_str());
        }

        //Check that the specified switch points are valid
        for (int switchpoint : wire_switchpoints.switchpoints) {
            if (switchpoint < 0) {
                archfpga_throw(__FILE__, __LINE__, "Invalid <wireconn> to_switchpoint '%d' (must be >= 0)\n", switchpoint, seg_name.c_str());
            }
            if (switchpoint >= seg_info->length) {
                archfpga_throw(__FILE__, __LINE__, "Invalid <wireconn> to_switchpoints '%d' (must be < %d)\n", switchpoint, seg_info->length);
            }
            //TODO: check that points correspond to valid sb locations
        }
    }
}

/*---- Functions for Parsing the Symbolic Switchblock Formulas ----*/

/* returns integer result according to the specified switchblock formula and data. formula may be piece-wise */
int get_sb_formula_raw_result(const char* formula, const t_formula_data& mydata) {
    /* the result of the formula will be an integer */
    int result = -1;

    /* check formula */
    if (nullptr == formula) {
        archfpga_throw(__FILE__, __LINE__, "in get_sb_formula_result: SB formula pointer NULL\n");
    } else if ('\0' == formula[0]) {
        archfpga_throw(__FILE__, __LINE__, "in get_sb_formula_result: SB formula empty\n");
    }

    /* parse based on whether formula is piece-wise or not */
    if (is_piecewise_formula(formula)) {
        //EXPERIMENTAL
        result = parse_piecewise_formula(formula, mydata);
    } else {
        result = parse_formula(formula, mydata);
    }

    return result;
}
