/* This file holds subroutines responsible for drawing inside clustered logic blocks.
 * The four main subroutines defined here are draw_internal_alloc_blk(),
 * draw_internal_init_blk(), draw_internal_draw_subblk(), and toggle_blk_internal().
 * When VPR graphics initially sets up, draw_internal_alloc_blk() will be called from
 * draw.c to allocate space for the structures needed for internal blks drawing->
 * Before any drawing, draw_internal_init_blk() will pre-compute a bounding box
 * for each sub-block in the pb_graph of every physical block type. When the menu button
 * "Blk Internal" is pressed, toggle_blk_internal() will enable internal blocks drawing->
 * Then, with each subsequent click on the button, toggle_blk_internal() will propel one
 * more level of pbs to be drawn. Draw_internal_draw_subblk() will be called whenever
 * new blocks need to be drawn, and this function is responsible for drawing sub-blocks
 * from the pre-computed bounding box values.
 *
 * Author: Long Yu (Mike) Wang
 * Date: August 2013, May 2014
 *
 * Author: Matthew J.P. Walker
 * Date: May 2014
 */

#ifndef NO_GRAPHICS

#    include <cstdio>
#    include <algorithm>
#    include <string.h>

#    include "vtr_assert.h"
#    include "vtr_memory.h"

#    include "intra_logic_block.h"
#    include "globals.h"
#    include "atom_netlist.h"
#    include "vpr_utils.h"
#    include "draw_global.h"
#    include "draw.h"
#    include "draw_color.h"

/************************* Subroutines local to this file. *******************************/

static void draw_internal_load_coords(int type_descrip_index, t_pb_graph_node* pb_graph_node, float parent_width, float parent_height);
static int draw_internal_find_max_lvl(const t_pb_type& pb_type);
static void draw_internal_calc_coords(int type_descrip_index, t_pb_graph_node* pb_graph_node, int num_pb_types, int type_index, int num_pb, int pb_index, float parent_width, float parent_height, float* blk_width, float* blk_height);
static bool is_top_lvl_block_highlighted(const ClusterBlockId blk_id, const t_logical_block_type_ptr type);
std::vector<AtomBlockId> collect_pb_atoms(const t_pb* pb);
void collect_pb_atoms_recurr(const t_pb* pb, std::vector<AtomBlockId>& atoms);
t_pb* highlight_sub_block_helper(const ClusterBlockId clb_index, t_pb* pb, const ezgl::point2d& local_pt, int max_depth);

#    ifndef NO_GRAPHICS
static void draw_internal_pb(const ClusterBlockId clb_index, t_pb* pb, const ezgl::rectangle& parent_bbox, const t_logical_block_type_ptr type, ezgl::renderer* g);
void draw_atoms_fanin_fanout_flylines(const std::vector<AtomBlockId>& atoms, ezgl::renderer* g);
void draw_selected_pb_flylines(ezgl::renderer* g);
void draw_one_logical_connection(const AtomPinId src_pin, const AtomPinId sink_pin, ezgl::renderer* g);
#    endif /* NO_GRAPHICS */

/************************* Subroutine definitions begin *********************************/

void draw_internal_alloc_blk() {
    t_draw_coords* draw_coords;
    t_pb_graph_node* pb_graph_head;

    /* Call accessor function to retrieve global variables. */
    draw_coords = get_draw_coords_vars();

    /* Create a vector holding coordinate information for each type of physical logic
     * block.
     */
    auto& device_ctx = g_vpr_ctx.device();
    draw_coords->blk_info.resize(device_ctx.logical_block_types.size());

    for (const auto& type : device_ctx.logical_block_types) {
        if (physical_tile_type(&type) == device_ctx.EMPTY_TYPE) {
            continue;
        }

        pb_graph_head = type.pb_graph_head;

        /* Create an vector with size equal to the total number of pins for each type
         * of physical logic block, in order to uniquely identify each sub-block in
         * the pb_graph of that type.
         */
        draw_coords->blk_info.at(type.index).subblk_array.resize(pb_graph_head->total_pb_pins);
    }
}

void draw_internal_init_blk() {
    /* Call accessor function to retrieve global variables. */
    t_draw_coords* draw_coords = get_draw_coords_vars();
    t_draw_state* draw_state = get_draw_state_vars();

    t_pb_graph_node* pb_graph_head_node;

    auto& device_ctx = g_vpr_ctx.device();
    for (const auto& type : device_ctx.physical_tile_types) {
        /* Empty block has no sub_blocks */
        if (&type == device_ctx.EMPTY_TYPE)
            continue;

        pb_graph_head_node = logical_block_type(&type)->pb_graph_head;
        int type_descriptor_index = type.index;

        int num_sub_tiles = type.capacity;

        // set the clb dimensions
        ezgl::rectangle& clb_bbox = draw_coords->blk_info.at(type_descriptor_index).subblk_array.at(0);
        ezgl::point2d bot_left = clb_bbox.bottom_left();
        ezgl::point2d top_right = clb_bbox.top_right();

        // note, that all clbs of the same type are the same size,
        // and that consequently we have *one* model for each type.
        bot_left = {0, 0};
        if (size_t(type.width) > device_ctx.grid.width() || size_t(type.height) > device_ctx.grid.height()) {
            // in this case, the clb certainly wont't fit, but this prevents
            // an out-of-bounds access, and provides some sort of (probably right)
            // value
            top_right = ezgl::point2d(
                (draw_coords->tile_x[1] - draw_coords->tile_x[0]) * (type.width - 1),
                (draw_coords->tile_y[1] - draw_coords->tile_y[0]) * (type.height - 1));
        } else {
            top_right = ezgl::point2d(
                draw_coords->tile_x[type.width - 1],
                draw_coords->tile_y[type.height - 1]);
        }
        top_right += ezgl::point2d(
            draw_coords->get_tile_width() / num_sub_tiles,
            draw_coords->get_tile_width());

        clb_bbox = ezgl::rectangle(bot_left, top_right);
        draw_internal_load_coords(type_descriptor_index, pb_graph_head_node,
                                  clb_bbox.width(), clb_bbox.height());

        /* Determine the max number of sub_block levels in the FPGA */
        draw_state->max_sub_blk_lvl = std::max(draw_internal_find_max_lvl(*logical_block_type(&type)->pb_type),
                                               draw_state->max_sub_blk_lvl);
    }
}

#    ifndef NO_GRAPHICS
void draw_internal_draw_subblk(ezgl::renderer* g) {
    t_draw_state* draw_state = get_draw_state_vars();
    if (!draw_state->show_blk_internal) {
        return;
    }
    auto& device_ctx = g_vpr_ctx.device();
    auto& cluster_ctx = g_vpr_ctx.clustering();
    auto& place_ctx = g_vpr_ctx.placement();

    for (size_t i = 0; i < device_ctx.grid.width(); i++) {
        for (size_t j = 0; j < device_ctx.grid.height(); j++) {
            /* Only the first block of a group should control drawing */
            if (device_ctx.grid[i][j].width_offset > 0 || device_ctx.grid[i][j].height_offset > 0)
                continue;

            /* Don't draw if tile is empty. This includes corners. */
            if (device_ctx.grid[i][j].type == device_ctx.EMPTY_TYPE)
                continue;

            int num_sub_tiles = device_ctx.grid[i][j].type->capacity;
            for (int k = 0; k < num_sub_tiles; ++k) {
                /* Don't draw if block is empty. */
                if (place_ctx.grid_blocks[i][j].blocks[k] == EMPTY_BLOCK_ID || place_ctx.grid_blocks[i][j].blocks[k] == INVALID_BLOCK_ID)
                    continue;

                /* Get block ID */
                ClusterBlockId bnum = place_ctx.grid_blocks[i][j].blocks[k];
                /* Safety check, that physical blocks exists in the CLB */
                if (cluster_ctx.clb_nlist.block_pb(bnum) == nullptr)
                    continue;
                draw_internal_pb(bnum, cluster_ctx.clb_nlist.block_pb(bnum), ezgl::rectangle({0, 0}, 0, 0), cluster_ctx.clb_nlist.block_type(bnum), g);
            }
        }
    }
    //Draw the atom-level net flylines for the selected pb
    //(inputs: blue, outputs: red, internal: orange)
    draw_selected_pb_flylines(g);
}
#    endif /* NO_GRAPHICS */

/* This function traverses through the pb_graph of a certain physical block type and
 * finds the maximum sub-block levels for that type.
 */
static int draw_internal_find_max_lvl(const t_pb_type& pb_type) {
    int i, j;
    t_mode mode;
    int max_levels = 0;

    /* If no modes, we have reached the end of pb_graph */
    if (pb_type.num_modes == 0)
        return (pb_type.depth);

    for (i = 0; i < pb_type.num_modes; ++i) {
        mode = pb_type.modes[i];

        for (j = 0; j < mode.num_pb_type_children; ++j) {
            max_levels = std::max(draw_internal_find_max_lvl(mode.pb_type_children[j]), max_levels);
        }
    }
    return max_levels;
}

/* Helper function for initializing bounding box values for each sub-block. This function
 * traverses through the pb_graph for a descriptor_type (given by type_descrip_index), and
 * calls helper function to compute bounding box values.
 */
static void draw_internal_load_coords(int type_descrip_index, t_pb_graph_node* pb_graph_node, float parent_width, float parent_height) {
    int i, j, k;
    t_pb_type* pb_type;
    int num_modes, num_children, num_pb;
    t_mode mode;
    float blk_width = 0.;
    float blk_height = 0.;

    /* Get information about the pb_type */
    pb_type = pb_graph_node->pb_type;
    num_modes = pb_type->num_modes;

    /* If no modes, we have reached the end of pb_graph */
    if (num_modes == 0)
        return;

    for (i = 0; i < num_modes; ++i) {
        mode = pb_type->modes[i];
        num_children = mode.num_pb_type_children;

        for (j = 0; j < num_children; ++j) {
            /* Find the number of instances for each child pb_type. */
            num_pb = mode.pb_type_children[j].num_pb;

            for (k = 0; k < num_pb; ++k) {
                /* Compute bound box for block. Don't call if pb_type is root-level pb. */
                draw_internal_calc_coords(type_descrip_index,
                                          &pb_graph_node->child_pb_graph_nodes[i][j][k],
                                          num_children, j, num_pb, k,
                                          parent_width, parent_height,
                                          &blk_width, &blk_height);

                /* Traverse to next level in the pb_graph */
                draw_internal_load_coords(type_descrip_index,
                                          &pb_graph_node->child_pb_graph_nodes[i][j][k],
                                          blk_width, blk_height);
            }
        }
    }
    return;
}

/* Helper function which computes bounding box values for a sub-block. The coordinates
 * are relative to the left and bottom corner of the parent block.
 */
static void
draw_internal_calc_coords(int type_descrip_index, t_pb_graph_node* pb_graph_node, int num_pb_types, int type_index, int num_pb, int pb_index, float parent_width, float parent_height, float* blk_width, float* blk_height) {
    float parent_drawing_width, parent_drawing_height;
    float sub_tile_x, sub_tile_y;
    float child_width, child_height;
    auto& device_ctx = g_vpr_ctx.device();
    auto& place_ctx = g_vpr_ctx.placement();

    // get the bbox for this pb type
    ezgl::rectangle& pb_bbox = get_draw_coords_vars()->blk_info.at(type_descrip_index).get_pb_bbox_ref(*pb_graph_node);

    const float FRACTION_PARENT_PADDING_X = 0.01;

    const float NORMAL_FRACTION_PARENT_HEIGHT = 0.90;
    float capacity_divisor = 1;
    const float FRACTION_PARENT_PADDING_BOTTOM = 0.01;

    const float FRACTION_CHILD_MARGIN_X = 0.025;
    const float FRACTION_CHILD_MARGIN_Y = 0.04;
    double left, bot, right, top;

    int capacity = device_ctx.physical_tile_types[type_descrip_index].capacity;
    if (capacity > 1 && device_ctx.grid.width() > 0 && device_ctx.grid.height() > 0 && place_ctx.grid_blocks[1][0].usage != 0
        && type_descrip_index == device_ctx.grid[1][0].type->index) {
        // that should test for io blocks, and setting capacity_divisor > 1
        // will squish every thing down
        capacity_divisor = capacity - 1;
    }

    /* Draw all child-level blocks in just most of the space inside their parent block. */
    parent_drawing_width = parent_width * (1 - FRACTION_PARENT_PADDING_X * 2);
    parent_drawing_height = parent_height * (NORMAL_FRACTION_PARENT_HEIGHT / capacity_divisor);

    /* The left and bottom corner (inside the parent block) of the space to draw
     * child blocks.
     */
    sub_tile_x = parent_width * FRACTION_PARENT_PADDING_X;
    sub_tile_y = parent_height * FRACTION_PARENT_PADDING_BOTTOM;

    /* Divide parent_drawing_width by the number of child types. */
    child_width = parent_drawing_width / num_pb_types;
    /* Divide parent_drawing_height by the number of instances of the pb_type. */
    child_height = parent_drawing_height / num_pb;

    /* The starting point to draw the physical block. */
    left = child_width * type_index + sub_tile_x + FRACTION_CHILD_MARGIN_X * child_width;
    bot = child_height * pb_index + sub_tile_y + FRACTION_CHILD_MARGIN_Y * child_height;

    /* Leave some space between different pb_types. */
    child_width *= 1 - FRACTION_CHILD_MARGIN_X * 2;
    /* Leave some space between different instances of the same type. */
    child_height *= 1 - FRACTION_CHILD_MARGIN_Y * 2;

    /* Endpoint for drawing the pb_type */
    right = left + child_width;
    top = bot + child_height;

    pb_bbox = ezgl::rectangle({right, top}, {left, bot});

    *blk_width = child_width;
    *blk_height = child_height;

    return;
}

#    ifndef NO_GRAPHICS
/* Helper subroutine to draw all sub-blocks. This function traverses through the pb_graph
 * which a netlist block can map to, and draws each sub-block inside its parent block. With
 * each click on the "Blk Internal" button, a new level is shown.
 */
static void draw_internal_pb(const ClusterBlockId clb_index, t_pb* pb, const ezgl::rectangle& parent_bbox, const t_logical_block_type_ptr type, ezgl::renderer* g) {
    t_draw_coords* draw_coords = get_draw_coords_vars();
    t_draw_state* draw_state = get_draw_state_vars();
    t_selected_sub_block_info& sel_sub_info = get_selected_sub_block_info();

    t_pb_type* pb_type = pb->pb_graph_node->pb_type;
    ezgl::rectangle temp = draw_coords->get_pb_bbox(clb_index, *pb->pb_graph_node);
    ezgl::rectangle abs_bbox = temp + parent_bbox.bottom_left();

    // if we've gone too far, don't draw anything
    if (pb_type->depth > draw_state->show_blk_internal) {
        return;
    }
    /// first draw box ///

    if (pb_type->depth == 0) {
        if (!is_top_lvl_block_highlighted(clb_index, type)) {
            // if this is a top level pb, and only if it isn't selected (ie. a funny colour),
            // overwrite it. (but stil draw the text)

            g->set_color(ezgl::WHITE);
            g->fill_rectangle(abs_bbox);
            g->set_color(ezgl::BLACK);
            g->set_line_dash(ezgl::line_dash::none);
            g->draw_rectangle(abs_bbox);
        }
    } else {
        if (pb->name != nullptr) {
            // If block is used, draw it in colour with solid border.
            g->set_line_dash(ezgl::line_dash::none);

            // type_index indicates what type of block.
            const int type_index = type->index;

            // determine default background color
            if (sel_sub_info.is_selected(pb->pb_graph_node, clb_index)) {
                g->set_color(SELECTED_COLOR);
            } else if (sel_sub_info.is_sink_of_selected(pb->pb_graph_node, clb_index)) {
                g->set_color(DRIVES_IT_COLOR);
            } else if (sel_sub_info.is_source_of_selected(pb->pb_graph_node, clb_index)) {
                g->set_color(DRIVEN_BY_IT_COLOR);
            } else if (pb_type->depth != draw_state->show_blk_internal && pb->child_pbs != nullptr) {
                g->set_color(ezgl::WHITE); // draw anything else that will have a child as white
            } else if (type_index < 3) {
                g->set_color(blk_LIGHTGREY);
            } else if (type_index < 3 + MAX_BLOCK_COLOURS) {
                g->set_color((block_colors[MAX_BLOCK_COLOURS + type_index - 3]));
            } else {
                g->set_color((block_colors[2 * MAX_BLOCK_COLOURS - 1]));
            }
        } else {
            // If block is not used, draw as empty block (ie. white
            // background with dashed border).

            g->set_line_dash(ezgl::line_dash::asymmetric_5_3);
            g->set_color(ezgl::WHITE);
        }
        g->fill_rectangle(abs_bbox);
        g->set_color(ezgl::BLACK);
        g->draw_rectangle(abs_bbox);
    }

    /// then draw text ///

    if (pb->name != nullptr) {
        g->set_font_size(16); // note: calc_text_xbound(...) assumes this is 16
        if (pb_type->depth == draw_state->show_blk_internal || pb->child_pbs == nullptr) {
            // If this pb is at the lowest displayed level, or has no more children, then
            // label it in the center with its type and name

            int type_len = strlen(pb_type->name);
            int name_len = strlen(pb->name);
            int tot_len = type_len + name_len;
            char* blk_tag = (char*)vtr::malloc((tot_len + 8) * sizeof(char));

            sprintf(blk_tag, "%s(%s)", pb_type->name, pb->name);

            g->draw_text(
                abs_bbox.center(),
                blk_tag,
                abs_bbox.width(),
                abs_bbox.height());

            free(blk_tag);
        } else {
            // else (ie. has chilren, and isn't at the lowest displayed level)
            // just label its type, and put it up at the top so we can see it
            g->draw_text(
                ezgl::point2d(abs_bbox.center_x(),
                              abs_bbox.top() - (abs_bbox.height()) / 15.0),
                pb_type->name,
                abs_bbox.width(),
                abs_bbox.height());
        }
    } else {
        // If child block is not used, label it only by its type
        g->draw_text(
            abs_bbox.center(),
            pb_type->name,
            abs_bbox.width(),
            abs_bbox.height());
    }

    /// now recurse on the child pbs. ///

    // return if no children, or this is an unusused pb,
    // or if going down will be too far down (this one is redundant, but for optimazition)
    if (pb->child_pbs == nullptr || pb->name == nullptr
        || pb_type->depth == draw_state->show_blk_internal) {
        return;
    }

    int num_child_types = pb->get_num_child_types();
    for (int i = 0; i < num_child_types; ++i) {
        if (pb->child_pbs[i] == nullptr) {
            continue;
        }

        int num_pb = pb->get_num_children_of_type(i);
        for (int j = 0; j < num_pb; ++j) {
            t_pb* child_pb = &pb->child_pbs[i][j];

            VTR_ASSERT(child_pb != nullptr);

            t_pb_type* pb_child_type = child_pb->pb_graph_node->pb_type;

            // don't go farther if 0 modes
            if (pb_child_type == nullptr || pb_child_type->num_modes == 0) {
                continue;
            }
            // now recurse
            draw_internal_pb(clb_index, child_pb, abs_bbox, type, g);
        }
    }
}

void draw_selected_pb_flylines(ezgl::renderer* g) {
    t_selected_sub_block_info& sel_sub_info = get_selected_sub_block_info();

    const t_pb* pb = sel_sub_info.get_selected_pb();

    if (pb) {
        auto atoms = collect_pb_atoms(pb);
        draw_atoms_fanin_fanout_flylines(atoms, g);
    }
}

void draw_atoms_fanin_fanout_flylines(const std::vector<AtomBlockId>& atoms, ezgl::renderer* g) {
    std::set<AtomBlockId> atoms_set(atoms.begin(), atoms.end());

    auto& atom_nl = g_vpr_ctx.atom().nlist;

    g->set_line_dash(ezgl::line_dash::none);
    g->set_line_width(2);

    for (AtomBlockId blk : atoms) {
        for (AtomPinId ipin : atom_nl.block_input_pins(blk)) {
            AtomNetId net = atom_nl.pin_net(ipin);

            AtomPinId net_driver = atom_nl.net_driver(net);
            AtomBlockId net_driver_blk = atom_nl.pin_block(net_driver);

            if (atoms_set.count(net_driver_blk)) {
                g->set_color(ezgl::ORANGE); //Internal
            } else {
                g->set_color(ezgl::BLUE); //External input
            }

            ezgl::point2d start = atom_pin_draw_coord(net_driver);
            ezgl::point2d end = atom_pin_draw_coord(ipin);
            g->draw_line(start, end);
            draw_triangle_along_line(g, start, end, 0.95, 40 * DEFAULT_ARROW_SIZE);
            draw_triangle_along_line(g, start, end, 0.05, 40 * DEFAULT_ARROW_SIZE);
        }

        for (AtomPinId opin : atom_nl.block_output_pins(blk)) {
            AtomNetId net = atom_nl.pin_net(opin);

            for (AtomPinId net_sink : atom_nl.net_sinks(net)) {
                AtomBlockId net_sink_blk = atom_nl.pin_block(net_sink);

                if (atoms_set.count(net_sink_blk)) {
                    g->set_color(ezgl::ORANGE); //Internal
                } else {
                    g->set_color(ezgl::RED); //External output
                }

                ezgl::point2d start = atom_pin_draw_coord(opin);
                ezgl::point2d end = atom_pin_draw_coord(net_sink);
                g->draw_line(start, end);
                draw_triangle_along_line(g, start, end, 0.95, 40 * DEFAULT_ARROW_SIZE);
                draw_triangle_along_line(g, start, end, 0.05, 40 * DEFAULT_ARROW_SIZE);
            }
        }
    }
}
#    endif /* NO_GRAPHICS */

std::vector<AtomBlockId> collect_pb_atoms(const t_pb* pb) {
    std::vector<AtomBlockId> atoms;
    collect_pb_atoms_recurr(pb, atoms);
    return atoms;
}

void collect_pb_atoms_recurr(const t_pb* pb, std::vector<AtomBlockId>& atoms) {
    auto& atom_ctx = g_vpr_ctx.atom();

    if (pb->is_primitive()) {
        //Base case
        AtomBlockId blk = atom_ctx.lookup.pb_atom(pb);
        if (blk) {
            atoms.push_back(blk);
        }
    } else {
        //Recurse
        VTR_ASSERT_DEBUG(atom_ctx.lookup.pb_atom(pb) == AtomBlockId::INVALID());

        for (int itype = 0; itype < pb->get_num_child_types(); ++itype) {
            for (int ichild = 0; ichild < pb->get_num_children_of_type(itype); ++ichild) {
                collect_pb_atoms_recurr(&pb->child_pbs[itype][ichild], atoms);
            }
        }
    }
}

#    ifndef NO_GRAPHICS
void draw_logical_connections(ezgl::renderer* g) {
    const t_selected_sub_block_info& sel_subblk_info = get_selected_sub_block_info();
    t_draw_state* draw_state = get_draw_state_vars();

    auto& atom_ctx = g_vpr_ctx.atom();

    g->set_line_dash(ezgl::line_dash::none);

    // iterate over all the atom nets
    for (auto net_id : atom_ctx.nlist.nets()) {
        AtomPinId driver_pin_id = atom_ctx.nlist.net_driver(net_id);
        AtomBlockId src_blk_id = atom_ctx.nlist.pin_block(driver_pin_id);
        const t_pb_graph_node* src_pb_gnode = atom_ctx.lookup.atom_pb_graph_node(src_blk_id);
        ClusterBlockId src_clb = atom_ctx.lookup.atom_clb(src_blk_id);
        bool src_is_selected = sel_subblk_info.is_in_selected_subtree(src_pb_gnode, src_clb);
        bool src_is_src_of_selected = sel_subblk_info.is_source_of_selected(src_pb_gnode, src_clb);

        // iterate over the sinks
        for (auto sink_pin_id : atom_ctx.nlist.net_sinks(net_id)) {
            AtomBlockId sink_blk_id = atom_ctx.nlist.pin_block(sink_pin_id);
            const t_pb_graph_node* sink_pb_gnode = atom_ctx.lookup.atom_pb_graph_node(sink_blk_id);
            ClusterBlockId sink_clb = atom_ctx.lookup.atom_clb(sink_blk_id);

            if (src_is_selected && sel_subblk_info.is_sink_of_selected(sink_pb_gnode, sink_clb)) {
                g->set_color(DRIVES_IT_COLOR);
            } else if (src_is_src_of_selected && sel_subblk_info.is_in_selected_subtree(sink_pb_gnode, sink_clb)) {
                g->set_color(DRIVEN_BY_IT_COLOR);
            } else if (draw_state->show_nets == DRAW_LOGICAL_CONNECTIONS && (draw_state->showing_sub_blocks() || src_clb != sink_clb)) {
                g->set_color(ezgl::BLACK); // if showing all, draw the other ones in black
            } else {
                continue; // not showing all, and not the sperified block, so skip
            }

            draw_one_logical_connection(driver_pin_id, sink_pin_id, g);
        }
    }
}
#    endif /* NO_GRAPHICS */

/**
 * Helper function for draw_one_logical_connection(...).
 * We return the index of the pin in the context of the *model*
 * This is used to determine where to draw connection start/end points
 *
 * The pin index in the model context is returned via pin_index.
 *
 * The total number of model pins (either inputs or outputs) is returned via total_pins
 *
 * The search inputs parameter tells this function to search
 * inputs (if true) or outputs (if false).
 */
void find_pin_index_at_model_scope(const AtomPinId pin_id, const AtomBlockId blk_id, int* pin_index, int* total_pins) {
    auto& atom_ctx = g_vpr_ctx.atom();

    AtomPortId port_id = atom_ctx.nlist.pin_port(pin_id);
    const t_model_ports* model_port = atom_ctx.nlist.port_model(port_id);

    //Total up the port widths
    //  Note that we do this on the model since the atom netlist doesn't include unused ports
    int pin_cnt = 0;
    *pin_index = -1; //initialize
    const t_model* model = atom_ctx.nlist.block_model(blk_id);
    for (const t_model_ports* port : {model->inputs, model->outputs}) {
        while (port) {
            if (port == model_port) {
                //This is the port the pin is associated with, record it's index

                //Get the pin index in the port
                int atom_port_index = atom_ctx.nlist.pin_port_bit(pin_id);

                //The index of this pin in the model is the pins counted so-far
                //(i.e. accross previous ports) plus the index in the port
                *pin_index = pin_cnt + atom_port_index;
            }

            //Running total of model pins seen so-far
            pin_cnt += port->size;

            port = port->next;
        }
    }

    VTR_ASSERT(*pin_index != -1);

    *total_pins = pin_cnt;
}

#    ifndef NO_GRAPHICS
/**
 * Draws ONE logical connection from src_pin in src_lblk to sink_pin in sink_lblk.
 * The *_abs_bbox parameters are for mild optmization, as the absolute bbox can be calculated
 * more effeciently elsewhere.
 */
void draw_one_logical_connection(const AtomPinId src_pin, const AtomPinId sink_pin, ezgl::renderer* g) {
    ezgl::point2d src_point = atom_pin_draw_coord(src_pin);
    ezgl::point2d sink_point = atom_pin_draw_coord(sink_pin);

    // draw a link connecting the pins.
    g->draw_line(src_point, sink_point);

    auto& atom_ctx = g_vpr_ctx.atom();
    if (atom_ctx.lookup.atom_clb(atom_ctx.nlist.pin_block(src_pin)) == atom_ctx.lookup.atom_clb(atom_ctx.nlist.pin_block(sink_pin))) {
        // if they are in the same clb, put one arrow in the center
        float center_x = (src_point.x + sink_point.x) / 2;
        float center_y = (src_point.y + sink_point.y) / 2;

        draw_triangle_along_line(g,
                                 center_x, center_y,
                                 src_point.x, sink_point.x,
                                 src_point.y, sink_point.y);
    } else {
        // if they are not, put 2 near each end
        draw_triangle_along_line(g, src_point, sink_point, 0.05);
        draw_triangle_along_line(g, src_point, sink_point, 0.95);
    }
}
#    endif /* NO_GRAPHICS */

/* This function checks whether a top-level clb has been highlighted. It does
 * so by checking whether the color in this block is default color.
 */
static bool is_top_lvl_block_highlighted(const ClusterBlockId blk_id, const t_logical_block_type_ptr type) {
    t_draw_state* draw_state;

    /* Call accessor function to retrieve global variables. */
    draw_state = get_draw_state_vars();

    if (type->index < 3) {
        if (draw_state->block_color[blk_id] == blk_LIGHTGREY)
            return false;
    } else if (type->index < 3 + MAX_BLOCK_COLOURS) {
        if (draw_state->block_color[blk_id] == block_colors[MAX_BLOCK_COLOURS + type->index - 3])
            //        if (draw_state->block_color[blk_id] == to_ezgl_color((color_types)(BISQUE + MAX_BLOCK_COLOURS + type->index - 3)))
            return false;
    } else {
        if (draw_state->block_color[blk_id] == block_colors[2 * MAX_BLOCK_COLOURS - 1])
            //        if (draw_state->block_color[blk_id] == to_ezgl_color((color_types)(BISQUE + 2 * MAX_BLOCK_COLOURS - 1)))
            return false;
    }

    return true;
}

int highlight_sub_block(const ezgl::point2d& point_in_clb, ClusterBlockId clb_index, t_pb* pb) {
    t_draw_state* draw_state = get_draw_state_vars();

    int max_depth = draw_state->show_blk_internal;

    t_pb* new_selected_sub_block = highlight_sub_block_helper(clb_index, pb, point_in_clb, max_depth);
    if (new_selected_sub_block == nullptr) {
        get_selected_sub_block_info().clear();
        return 1;
    } else {
        get_selected_sub_block_info().set(new_selected_sub_block, clb_index);
        return 0;
    }
}

/**
 * The recursive part of highlight_sub_block. finds which pb is under
 * the given location. local_pt is relative to the given pb, and pb should
 * be in clb.
 */
t_pb* highlight_sub_block_helper(const ClusterBlockId clb_index, t_pb* pb, const ezgl::point2d& local_pt, int max_depth) {
    t_draw_coords* draw_coords = get_draw_coords_vars();
    t_pb_type* pb_type = pb->pb_graph_node->pb_type;

    // check to see if we are past the displayed level,
    // if pb has children,
    // and if pb is dud
    if (pb_type->depth + 1 > max_depth
        || pb->child_pbs == nullptr
        || pb_type->num_modes == 0) {
        return nullptr;
    }

    int num_child_types = pb->get_num_child_types();

    // Iterate through each type of child pb, and each pb of that type.
    for (int i = 0; i < num_child_types; ++i) {
        int num_children_of_type = pb->get_num_children_of_type(i);

        for (int j = 0; j < num_children_of_type; ++j) {
            if (pb->child_pbs[i] == nullptr) {
                continue;
            }

            t_pb* child_pb = &pb->child_pbs[i][j];
            t_pb_graph_node* pb_child_node = child_pb->pb_graph_node;

            // get the bbox for this child
            const ezgl::rectangle& bbox = draw_coords->get_pb_bbox(clb_index, *pb_child_node);

            // If child block is being used, check if it intersects
            if (child_pb->name != nullptr && bbox.contains(local_pt)) {
                // check farther down the graph, see if we can find
                // something more specific.
                t_pb* subtree_result = highlight_sub_block_helper(
                    clb_index, child_pb, local_pt - bbox.bottom_left(), max_depth);
                if (subtree_result != nullptr) {
                    // we found something more specific.
                    return subtree_result;
                } else {
                    // couldn't find something more specific, return parent
                    return child_pb;
                }
            }
        }
    }
    return nullptr;
}

t_selected_sub_block_info& get_selected_sub_block_info() {
    // used to keep track of the selected sub-block.
    static t_selected_sub_block_info selected_sub_block_info;
    return selected_sub_block_info;
}

/*
 * Begin definition of t_selected_sub_block_info functions.
 */

t_selected_sub_block_info::t_selected_sub_block_info() {
    clear();
}

template<typename HashType>

void add_all_children(const t_pb* pb, const ClusterBlockId clb_index, std::unordered_set<t_selected_sub_block_info::gnode_clb_pair, HashType>& set) {
    if (pb == nullptr) {
        return;
    }

    set.insert(t_selected_sub_block_info::gnode_clb_pair(pb->pb_graph_node, clb_index));

    int num_child_types = pb->get_num_child_types();
    for (int i = 0; i < num_child_types; ++i) {
        int num_children_of_type = pb->get_num_children_of_type(i);
        for (int j = 0; j < num_children_of_type; ++j) {
            add_all_children(&pb->child_pbs[i][j], clb_index, set);
        }
    }
}

void t_selected_sub_block_info::set(t_pb* new_selected_sub_block, const ClusterBlockId new_containing_block_index) {
    selected_pb = new_selected_sub_block;
    selected_pb_gnode = (selected_pb == nullptr) ? nullptr : selected_pb->pb_graph_node;
    containing_block_index = new_containing_block_index;
    sinks.clear();
    sources.clear();
    in_selected_subtree.clear();

    auto& atom_ctx = g_vpr_ctx.atom();

    if (has_selection()) {
        add_all_children(selected_pb, containing_block_index, in_selected_subtree);

        for (auto blk_id : atom_ctx.nlist.blocks()) {
            const ClusterBlockId clb = atom_ctx.lookup.atom_clb(blk_id);
            const t_pb_graph_node* pb_graph_node = atom_ctx.lookup.atom_pb_graph_node(blk_id);
            // find the atom block that corrisponds to this pb.
            if (is_in_selected_subtree(pb_graph_node, clb)) {
                //Collect the sources of all nets driving this node
                for (auto pin_id : atom_ctx.nlist.block_input_pins(blk_id)) {
                    AtomNetId net_id = atom_ctx.nlist.pin_net(pin_id);
                    AtomPinId driver_pin_id = atom_ctx.nlist.net_driver(net_id);

                    AtomBlockId src_blk = atom_ctx.nlist.pin_block(driver_pin_id);

                    const ClusterBlockId src_clb = atom_ctx.lookup.atom_clb(src_blk);
                    const t_pb_graph_node* src_pb_graph_node = atom_ctx.lookup.atom_pb_graph_node(src_blk);

                    sources.insert(gnode_clb_pair(src_pb_graph_node, src_clb));
                }

                //Collect the sinks of all nets driven by this node
                for (auto pin_id : atom_ctx.nlist.block_output_pins(blk_id)) {
                    AtomNetId net_id = atom_ctx.nlist.pin_net(pin_id);
                    for (auto sink_pin_id : atom_ctx.nlist.net_sinks(net_id)) {
                        AtomBlockId sink_blk = atom_ctx.nlist.pin_block(sink_pin_id);

                        const ClusterBlockId sink_clb = atom_ctx.lookup.atom_clb(sink_blk);
                        const t_pb_graph_node* sink_pb_graph_node = atom_ctx.lookup.atom_pb_graph_node(sink_blk);

                        sinks.insert(gnode_clb_pair(sink_pb_graph_node, sink_clb));
                    }
                }
            }
        }
    }
}

void t_selected_sub_block_info::clear() {
    set(nullptr, ClusterBlockId::INVALID());
}

t_pb* t_selected_sub_block_info::get_selected_pb() const { return selected_pb; }

t_pb_graph_node* t_selected_sub_block_info::get_selected_pb_gnode() const { return selected_pb_gnode; }

ClusterBlockId t_selected_sub_block_info::get_containing_block() const { return containing_block_index; }

bool t_selected_sub_block_info::has_selection() const {
    return get_selected_pb_gnode() != nullptr && get_containing_block() != ClusterBlockId::INVALID();
}

bool t_selected_sub_block_info::is_selected(const t_pb_graph_node* test, const ClusterBlockId clb_index) const {
    return get_selected_pb_gnode() == test && get_containing_block() == clb_index;
}

bool t_selected_sub_block_info::is_sink_of_selected(const t_pb_graph_node* test, const ClusterBlockId clb_index) const {
    return sinks.find(gnode_clb_pair(test, clb_index)) != sinks.end();
}

bool t_selected_sub_block_info::is_source_of_selected(const t_pb_graph_node* test, const ClusterBlockId clb_index) const {
    return sources.find(gnode_clb_pair(test, clb_index)) != sources.end();
}

bool t_selected_sub_block_info::is_in_selected_subtree(const t_pb_graph_node* test, const ClusterBlockId clb_index) const {
    return in_selected_subtree.find(gnode_clb_pair(test, clb_index)) != in_selected_subtree.end();
}

/*
 * Begin definition of t_selected_sub_block_info::clb_pin_tuple functions.
 */

t_selected_sub_block_info::clb_pin_tuple::clb_pin_tuple(ClusterBlockId clb_index_, const t_pb_graph_node* pb_gnode_)
    : clb_index(clb_index_)
    , pb_gnode(pb_gnode_) {
}

t_selected_sub_block_info::clb_pin_tuple::clb_pin_tuple(const AtomPinId atom_pin) {
    auto& atom_ctx = g_vpr_ctx.atom();
    clb_index = atom_ctx.lookup.atom_clb(atom_ctx.nlist.pin_block(atom_pin));
    pb_gnode = atom_ctx.lookup.atom_pb_graph_node(atom_ctx.nlist.pin_block(atom_pin));
}

bool t_selected_sub_block_info::clb_pin_tuple::operator==(const clb_pin_tuple& rhs) const {
    return clb_index == rhs.clb_index && pb_gnode == rhs.pb_gnode;
}

/*
 * Begin definition of t_selected_sub_block_info::gnode_clb_pair functions
 */

t_selected_sub_block_info::gnode_clb_pair::gnode_clb_pair(const t_pb_graph_node* pb_gnode_, const ClusterBlockId clb_index_)
    : pb_gnode(pb_gnode_)
    , clb_index(clb_index_) {
}

bool t_selected_sub_block_info::gnode_clb_pair::operator==(const gnode_clb_pair& rhs) const {
    return clb_index == rhs.clb_index
           && pb_gnode == rhs.pb_gnode;
}

#endif // NO_GRAPHICS
