#!/usr/bin/env python3

from lib.rr_graph import graph2
from lib.rr_graph import tracks
from lib.rr_graph import points
import lib.rr_graph_xml.graph2 as xml_graph2


# bi-directional channels
def create_tracks(graph, grid_width, grid_height, rcw, verbose=False):
    print("Creating tracks, channel width: %d" % rcw)

    # Not strictly required, but VPR wants this I think?
    assert rcw % 2 == 0

    def alt_pos(begin, end, swap):
        if swap:
            return end, begin, graph2.NodeDirection.DEC_DIR
        else:
            return begin, end, graph2.NodeDirection.INC_DIR

    # chanx going entire width
    for y in range(0, grid_height - 1):
        for tracki in range(rcw):
            begin, end, direction = alt_pos(
                (1, y), (grid_width - 2, y), tracki % 2 == 1
            )

            graph.add_track(
                track=tracks.Track(
                    direction='X',
                    x_low=begin[0],
                    x_high=end[0],
                    y_low=begin[1],
                    y_high=end[1],
                ),
                segment_id=graph.segments[0].id,
                capacity=1,
                direction=direction,
                name="CHANX{:04d}@{:04d}".format(y, tracki),
            )

    # chany going entire height
    for x in range(0, grid_width - 1):
        for tracki in range(rcw):
            begin, end, direction = alt_pos(
                (x, 1), (x, grid_height - 2), tracki % 2 == 1
            )

            graph.add_track(
                track=tracks.Track(
                    direction='Y',
                    x_low=begin[0],
                    x_high=end[0],
                    y_low=begin[1],
                    y_high=end[1],
                ),
                segment_id=graph.segments[0].id,
                capacity=1,
                direction=direction,
                name="CHANY{:04d}@{:04d}".format(x, tracki),
            )


def create_tracks_from_points(
        name, graph, unique_pos, short, grid_width, grid_height
):
    xs, ys = points.decompose_points_into_tracks(
        unique_pos,
        grid_width,
        grid_height,
        right_only=True,
    )
    tracks_list, track_connections = tracks.make_tracks(
        xs, ys, unique_pos, grid_width, grid_height
    )
    tracks_model = tracks.Tracks(tracks_list, track_connections)
    nodes = []
    for idx, track in enumerate(tracks_list):
        nodes.append(
            graph.add_track(
                track=track,
                segment_id=graph.segments[0].id,
                capacity=1,
                name="{}{}".format(name, idx),
            )
        )

    for aidx, bidx in track_connections:
        graph.add_edge(
            src_node=nodes[aidx],
            sink_node=nodes[bidx],
            switch_id=short,
        )
        graph.add_edge(
            src_node=nodes[bidx],
            sink_node=nodes[aidx],
            switch_id=short,
        )

    return nodes, tracks_model


def create_global_constant_tracks(graph, mux, short, grid_width, grid_height):
    """ Create channels for global fanout """
    unique_pos = set()

    for x in range(grid_width):
        for y in range(grid_height):
            if x == 0:
                continue
            if y == 0:
                continue
            if x == grid_width - 1:
                continue
            if y == grid_height - 1:
                continue
            if x == grid_width - 2 and y == grid_height - 2:
                continue

            unique_pos.add((x, y))

    vcc_nodes, vcc_tracks = create_tracks_from_points(
        "VCC", graph, unique_pos, short, grid_width, grid_height
    )
    gnd_nodes, gnd_tracks = create_tracks_from_points(
        "GND", graph, unique_pos, short, grid_width, grid_height
    )

    vcc_pin = graph.create_pin_name_from_tile_type_and_pin('VCC', 'VCC')
    gnd_pin = graph.create_pin_name_from_tile_type_and_pin('GND', 'GND')

    found_vcc = False
    found_gnd = False

    for loc in graph.grid:
        block_type = graph.block_types[loc.block_type_id]

        for pin_class in block_type.pin_class:
            for pin in pin_class.pin:
                if pin.name == vcc_pin:
                    nodes = vcc_nodes
                    tracks = vcc_tracks
                    found_vcc = True
                elif pin.name == gnd_pin:
                    nodes = gnd_nodes
                    tracks = gnd_tracks
                    found_gnd = True
                else:
                    continue

                pin_map = {}

                for pin_node, pin_side in graph.loc_pin_map[(loc.x, loc.y,
                                                             pin.ptc)]:
                    pin_map[pin_side] = pin_node

                made_connection = False
                for pin_dir, idx in tracks.get_tracks_for_wire_at_coord(
                    (loc.x, loc.y)).items():
                    if pin_dir in pin_map:
                        made_connection = True
                        graph.add_edge(
                            src_node=pin_map[pin_side],
                            sink_node=nodes[idx],
                            switch_id=mux,
                        )
                        break

                assert made_connection, (pin, pin_map)

    assert found_vcc
    assert found_gnd


def channel_common(node):
    """ Return the value of the channel that is common.

    Args:
        node (graph2.Node): Node to get common dimension.

    """
    if node.type == graph2.NodeType.CHANX:
        assert node.loc.y_low == node.loc.y_high
        return node.loc.y_low
    elif node.type == graph2.NodeType.CHANY:
        assert node.loc.x_low == node.loc.x_high
        return node.loc.x_low
    else:
        assert False, node.type


def channel_start(node):
    """ Return the start value of the channel

    Args:
        node (graph2.Node): Node to get start dimension.

    """
    if node.type == graph2.NodeType.CHANX:
        return node.loc.x_low
    elif node.type == graph2.NodeType.CHANY:
        return node.loc.y_low
    else:
        assert False, node.type


def walk_pins(graph):
    """ Yields all pins from grid.

    Yield is tuple (graph2.GridLoc, graph2.PinClass, graph2.Pin, pin node idx, tracks.Direction).

    """
    for loc in graph.grid:
        block_type = graph.block_types[loc.block_type_id]

        for pin_class_idx, pin_class in enumerate(block_type.pin_class):
            for pin in pin_class.pin:
                for pin_node, pin_side in graph.loc_pin_map[(loc.x, loc.y,
                                                             pin.ptc)]:
                    yield loc, pin_class, pin, pin_node, pin_side


def connect_blocks_to_tracks(
        graph, grid_width, grid_height, rcw, switch, verbose=False
):
    ytracks = {}

    for inode in graph.tracks:
        if graph.nodes[inode].type == graph2.NodeType.CHANX:
            continue
        elif graph.nodes[inode].type == graph2.NodeType.CHANY:
            x = channel_common(graph.nodes[inode])

            if x not in ytracks:
                ytracks[x] = []
            ytracks[x].append(inode)
        else:
            assert False, graph.nodes[inode]

    special_pins = set(
        (
            graph.create_pin_name_from_tile_type_and_pin('TILE', 'COUT'),
            graph.create_pin_name_from_tile_type_and_pin('TILE', 'CIN'),
            graph.create_pin_name_from_tile_type_and_pin('VCC', 'VCC'),
            graph.create_pin_name_from_tile_type_and_pin('GND', 'GND'),
        )
    )

    print("Indexing nodes")
    print("Skipping connecting block pins to CHANX")
    print("Connecting left-right block pins to CHANY")

    # Walk every pin and connect them to every track on the left or right,
    # depending on pin direction
    #
    # Pins in the TOP/BOTTOM direction are asserted to be the carry pins.
    for loc, pin_class, pin, pin_node, pin_side in walk_pins(graph):
        if pin.name in special_pins:
            continue

        if pin_side == tracks.Direction.LEFT:
            if loc.x == 0:
                continue
            tracks_for_pin = ytracks[loc.x - 1]
        elif pin_side == tracks.Direction.RIGHT:
            if loc.x == grid_width - 1:
                continue
            tracks_for_pin = ytracks[loc.x]
        else:
            assert False, pin_side

        if pin_class.type == graph2.PinType.OUTPUT:
            for track_inode in tracks_for_pin:
                graph.add_edge(
                    src_node=pin_node,
                    sink_node=track_inode,
                    switch_id=switch,
                )
        elif pin_class.type == graph2.PinType.INPUT:
            for track_inode in tracks_for_pin:
                graph.add_edge(
                    src_node=track_inode,
                    sink_node=pin_node,
                    switch_id=switch,
                )


def connect_tracks_to_tracks(graph, switch, verbose=False):
    print("Connecting tracks to tracks")

    def try_connect(ainode, binode):
        """ Connect channel at ainode and binode if possible.

        Args:
            ainode (int): Node index of destination channel
            binode (int): Node index of source channel.

        """
        atrack = graph.nodes[ainode]
        btrack = graph.nodes[binode]

        # Check if source channel can connect to destinatio channel.
        # Note this code assumes unidirectional channels are in use.
        if (btrack.direction == graph2.NodeDirection.INC_DIR
                and channel_start(btrack) <= channel_common(atrack)) \
            or (btrack.direction == graph2.NodeDirection.DEC_DIR
                and channel_start(btrack) >= channel_common(atrack)):
            graph.add_edge(binode, ainode, switch)

    xtracks = []
    ytracks = []

    for inode in graph.tracks:
        if graph.nodes[inode].type == graph2.NodeType.CHANX:
            xtracks.append(inode)
        elif graph.nodes[inode].type == graph2.NodeType.CHANY:
            ytracks.append(inode)
        else:
            assert False, graph.nodes[inode]

    for xinode in xtracks:
        for yinode in ytracks:
            try_connect(xinode, yinode)
            try_connect(yinode, xinode)


def rebuild_graph(fn, fn_out, rcw=6, verbose=False):
    """
    Add rcw tracks spanning full channel to both X and Y channels
    Connect all of those to all the adjacent pins
    Fully connect tracks at intersections
    For intersections this means we actually have two edges per intersection
    since source and sink must be specified
    """

    print('Importing input g')
    xml_graph = xml_graph2.Graph(
        fn,
        output_file_name=fn_out,
    )

    graph = xml_graph.graph

    grid_width = max(p.x for p in graph.grid) + 1
    grid_height = max(p.y for p in graph.grid) + 1

    mux = graph.get_switch_id('mux')

    try:
        short = graph.get_switch_id('short')
    except KeyError:
        short = xml_graph.add_switch(
            graph2.Switch(
                id=None,
                name='short',
                type=graph2.SwitchType.SHORT,
                timing=None,
                sizing=graph2.SwitchSizing(
                    mux_trans_size=0,
                    buf_size=0,
                ),
            )
        )

    create_tracks(graph, grid_width, grid_height, rcw, verbose=verbose)
    create_global_constant_tracks(graph, mux, short, grid_width, grid_height)
    connect_blocks_to_tracks(graph, grid_width, grid_height, rcw, switch=mux)
    connect_tracks_to_tracks(graph, switch=mux, verbose=verbose)
    print("Completed rebuild")

    xml_graph.root_attrib["tool_version"] = "dev"
    xml_graph.root_attrib["tool_comment"] = "Generated from black magic"

    channels_obj = graph.create_channels(pad_segment=graph.segments[0].id)

    xml_graph.serialize_to_xml(
        channels_obj=channels_obj,
        nodes_obj=graph.nodes,
        edges_obj=graph.edges
    )


def main():
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument("--verbose", action='store_true')
    parser.add_argument("--route_chan_width", type=int, default=20)
    parser.add_argument("--read_rr_graph")
    parser.add_argument("--write_rr_graph")
    args = parser.parse_args()

    rebuild_graph(
        args.read_rr_graph,
        args.write_rr_graph,
        rcw=args.route_chan_width,
        verbose=args.verbose
    )


if __name__ == "__main__":
    main()
