"""
Utility functions for making hop connections between switchboxes and locat
switchbox - tile connections.
"""
import re

from data_structs import SwitchboxPinType, Loc, OPPOSITE_DIRECTION, \
    Connection, ConnectionLoc, ConnectionType, PinDirection
from utils import find_cell_in_tile

# =============================================================================

# A regex for regular HOP wires
RE_HOP_WIRE = re.compile(r"^([HV])([0-9])([TBLR])([0-9])")

# A regex for HOP offsets
RE_HOP = re.compile(r"^([\[\]A-Za-z0-9_]+)_([TBLR])([0-9]+)$")

# =============================================================================


def hop_to_str(offset):
    """
    Formats a two-character string that uniquely identifies the hop offset.

    >>> hop_to_str([-3, 0])
    'L3'
    >>> hop_to_str([1, 0])
    'R1'
    >>> hop_to_str([0, -2])
    'T2'
    >>> hop_to_str([0, +7])
    'B7'
    """

    # Zero offsets are not allowed
    assert offset[0] != 0 or offset[1] != 0, offset

    # Diagonal offsets are not allowed
    if offset[0] != 0:
        assert offset[1] == 0, offset
    if offset[1] != 0:
        assert offset[0] == 0, offset

    # Horizontal
    if offset[1] == 0:
        if offset[0] > 0:
            return "R{}".format(+offset[0])
        if offset[0] < 0:
            return "L{}".format(-offset[0])

    # Vertical
    if offset[0] == 0:
        if offset[1] > 0:
            return "B{}".format(+offset[1])
        if offset[1] < 0:
            return "T{}".format(-offset[1])

    # Should not happen
    assert False, offset


def get_name_and_hop(name):
    """
    Extracts wire name and hop offset given a hop wire name. Returns a tuple
    with (name, (hop_x, hop_y)).

    When a wire name does not contain hop definition then the function
    returns (name, None).

    Note: the hop offset is defined from the input (destination) perspective.

    >>> get_name_and_hop("WIRE")
    ('WIRE', None)
    >>> get_name_and_hop("V4T0_B3")
    ('V4T0', (0, 3))
    >>> get_name_and_hop("H2R1_L1")
    ('H2R1', (-1, 0))
    >>> get_name_and_hop("RAM_A[5]_T2")
    ('RAM_A[5]', (0, -2))
    """

    # Check if the name defines a hop.
    match = RE_HOP.match(name)
    if match is None:
        return name, None

    # Hop length
    length = int(match.group(3))
    assert length in [1, 2, 3, 4], (name, length)

    # Hop direction
    direction = match.group(2)
    if direction == "T":
        hop = (0, -length)
    elif direction == "B":
        hop = (0, +length)
    elif direction == "L":
        hop = (-length, 0)
    elif direction == "R":
        hop = (+length, 0)
    else:
        assert False, (name, direction)

    return match.group(1), hop


def is_regular_hop_wire(name):
    """
    Returns True if the wire name defines a regular HOP wire. Also performs
    sanity checks of the name.

    >>> is_regular_hop_wire("H1R5")
    True
    >>> is_regular_hop_wire("V4B7")
    True
    >>> is_regular_hop_wire("WIRE")
    False
    >>> is_regular_hop_wire("MULT_Addr[17]_R3")
    False
    """

    # Match
    match = RE_HOP_WIRE.match(name)
    if match is None:
        return False

    # Check length
    length = int(match.group(2))
    assert length in [1, 2, 4], name

    # Check orientation
    orientation = match.group(1)
    direction = match.group(3)

    if orientation == "H":
        assert direction in ["L", "R"], name
    if orientation == "V":
        assert direction in ["T", "B"], name

    return True


# =============================================================================


def build_tile_connections(
        tile_types, tile_grid, switchbox_types, switchbox_grid
):
    """
    Build local and foreign connections between all switchboxes and tiles.
    """
    connections = []

    # Process switchboxes
    for loc, switchbox_type in switchbox_grid.items():
        switchbox = switchbox_types[switchbox_type]

        # Get pins
        sbox_pins = [
            pin for pin in switchbox.pins
            if pin.type in [SwitchboxPinType.LOCAL, SwitchboxPinType.FOREIGN]
        ]

        for sbox_pin in sbox_pins:
            tile = None

            # A local connection
            if sbox_pin.type == SwitchboxPinType.LOCAL:
                pin_name = sbox_pin.name
                tile_loc = loc

            # A foreign connection
            elif sbox_pin.type == SwitchboxPinType.FOREIGN:

                # Get the hop offset
                pin_name, hop = get_name_and_hop(sbox_pin.name)
                assert hop is not None, sbox_pin

                tile_loc = Loc(x=loc.x + hop[0], y=loc.y + hop[1], z=loc.z)

            # Get the tile
            if tile_loc not in tile_grid:
                print(
                    "WARNING: No tile at loc '{}' for pin '{}'".format(
                        tile_loc, sbox_pin.name
                    )
                )
                continue

            tile = tile_types[tile_grid[tile_loc].type]

            # Find the pin in the tile
            for pin in tile.pins:
                if pin.direction == OPPOSITE_DIRECTION[sbox_pin.direction]:

                    # Check if the pin name refers to the full tile pin name
                    # ie. with the cell name.
                    if pin.name == pin_name:
                        tile_pin = pin
                        break

                    # Split the pin name into cell name + pin name, check only
                    # if the latter matches.
                    cell, name = pin.name.split("_", maxsplit=1)
                    if name == pin_name:
                        tile_pin = pin
                        break
            else:
                tile_pin = None

            # Pin not found
            if tile_pin is None:
                print(
                    "WARNING: No pin in tile at '{}' found for switchbox pin '{}' of '{}' at '{}'"
                    .format(tile_loc, sbox_pin.name, switchbox.type, loc)
                )
                continue

            # Add the connection
            src = ConnectionLoc(
                loc=loc,
                pin=sbox_pin.name,
                type=ConnectionType.SWITCHBOX,
            )
            dst = ConnectionLoc(
                loc=tile_loc,
                pin=tile_pin.name,
                type=ConnectionType.TILE,
            )

            if sbox_pin.direction == PinDirection.OUTPUT:
                connection = Connection(src=src, dst=dst, is_direct=False)
            if sbox_pin.direction == PinDirection.INPUT:
                connection = Connection(src=dst, dst=src, is_direct=False)

            connections.append(connection)

    return connections


# =============================================================================


def build_hop_connections(switchbox_types, switchbox_grid):
    """
    Builds HOP connections between switchboxes.
    """
    connections = []

    # Determine the switchbox grid limits
    xs = set([loc.x for loc in switchbox_grid.keys()])
    ys = set([loc.y for loc in switchbox_grid.keys()])
    loc_min = Loc(min(xs), min(ys), 0)
    loc_max = Loc(max(xs), max(ys), 0)

    # Identify all connections that go out of switchboxes
    for dst_loc, dst_switchbox_type in switchbox_grid.items():
        dst_switchbox = switchbox_types[dst_switchbox_type]

        # Process HOP inputs. No need for looping over outputs as each output
        # should go into a HOP input.
        dst_pins = [
            pin for pin in dst_switchbox.inputs.values()
            if pin.type == SwitchboxPinType.HOP
        ]
        for dst_pin in dst_pins:

            # Parse the name, determine hop offset. Skip non-hop wires.
            hop_name, hop_ofs = get_name_and_hop(dst_pin.name)
            if hop_ofs is None:
                continue

            # Check if we don't hop outside the FPGA grid.
            src_loc = Loc(dst_loc.x + hop_ofs[0], dst_loc.y + hop_ofs[1], 0)
            if src_loc.x < loc_min.x or src_loc.x > loc_max.x:
                continue
            if src_loc.y < loc_min.y or src_loc.y > loc_max.y:
                continue

            # Get the switchbox at the source location
            if src_loc not in switchbox_grid:
                print(
                    "WARNING: No switchbox at '{}' for input '{}' of switchbox '{}' at '{}'"
                    .format(
                        src_loc, dst_pin.name, dst_switchbox_type, dst_loc
                    )
                )
                continue

            src_switchbox_type = switchbox_grid[src_loc]
            src_switchbox = switchbox_types[src_switchbox_type]

            # Check if there is a matching input pin in that switchbox
            src_pins = [
                pin for pin in src_switchbox.outputs.values()
                if pin.name == hop_name
            ]

            if len(src_pins) != 1:
                print(
                    "WARNING: No output pin '{}' in switchbox '{}'"
                    " at '{}' for input '{}' of switchbox '{}' at '{}'".format(
                        hop_name, src_switchbox_type, src_loc, dst_pin.name,
                        dst_switchbox_type, dst_loc
                    )
                )
                continue

            src_pin = src_pins[0]

            # Add the connection
            connection = Connection(
                src=ConnectionLoc(
                    loc=src_loc,
                    pin=src_pin.name,
                    type=ConnectionType.SWITCHBOX,
                ),
                dst=ConnectionLoc(
                    loc=dst_loc,
                    pin=dst_pin.name,
                    type=ConnectionType.SWITCHBOX,
                ),
                is_direct=False
            )

            connections.append(connection)

    return connections


# =============================================================================


def find_clock_cell(alias, tile_grid):

    for loc, tile in tile_grid.items():
        if tile is None:
            continue

        # Must have at least one "CLOCK" cell
        clock_cells = [c for c in tile.cells if c.type == "CLOCK"]
        if len(clock_cells) == 0:
            continue

        for cell in clock_cells:
            if cell.alias == alias:
                return loc, tile, cell

    return None, None, None


def build_gmux_qmux_connections(
        tile_types, tile_grid, switchbox_types, switchbox_grid, clock_cells
):

    # Define names of all global clock wires.
    # Each global clock mux as an implicitly defined output equal to its name.
    clock_wires = list(clock_cells.keys())

    # GMUX "IP" inputs are global clock wires too
    for clock_mux in clock_cells.values():
        if clock_mux.type == "GMUX":
            clock_wires.append(clock_mux.pin_map["IP"])

    # Conections between clock cells (muxes)
    connections = []
    for clock_cell in clock_cells.values():

        for pin_name, pin_conn in clock_cell.pin_map.items():

            # Destination pin name. Treat CAND and QMUX destinations
            # differently as there are going to be no tiles for them.
            if clock_cell.type in ["CAND", "QMUX"]:
                dst_type = ConnectionType.CLOCK
                dst_pin_name = "{}.{}".format(clock_cell.name, pin_name)

            else:
                dst_tile = tile_grid[clock_cell.loc]
                dst_cell = find_cell_in_tile(clock_cell.name, dst_tile)
                dst_type = ConnectionType.TILE

                dst_pin_name = "{}{}_{}".format(
                    dst_cell.type, dst_cell.index, pin_name
                )

            # This pin connects to a global clock wire
            if pin_conn in clock_wires:

                # Get the other cell
                other_cell = clock_cells.get(pin_conn, None)

                # Not found in the clock cells. Probably it is the CLOCK cell
                # try finding it by its name / alias
                if other_cell is None:

                    src_loc, src_tile, src_cell = \
                        find_clock_cell(pin_conn, tile_grid)

                    # Didint find the cell
                    if src_cell is None:
                        print(
                            "WARNING: No source cell for global clock wire '{}'"
                            .format(pin_conn)
                        )
                        continue

                    # Connect to the cell
                    src_type = ConnectionType.TILE
                    src_pin_name = "{}{}_{}".format(
                        src_cell.type, src_cell.index, "IC"
                    )

                    is_direct = True

                # Connect to the other cell
                else:
                    src_loc = other_cell.loc

                    # Source pin name. Tread CAND and QMUX differently as there
                    # are going to be no tiles for them.
                    if other_cell.type in ["CAND", "QMUX"]:
                        src_type = ConnectionType.CLOCK
                        src_pin_name = "{}.{}".format(other_cell.name, "IZ")

                    else:
                        src_tile = tile_grid[other_cell.loc]
                        src_cell = find_cell_in_tile(other_cell.name, src_tile)
                        src_type = ConnectionType.TILE

                        src_pin_name = "{}{}_{}".format(
                            src_cell.type, src_cell.index, "IZ"
                        )

                    is_direct = False

                # Make the connection
                connections.append(
                    Connection(
                        src=ConnectionLoc(
                            loc=src_loc, pin=src_pin_name, type=src_type
                        ),
                        dst=ConnectionLoc(
                            loc=clock_cell.loc,
                            pin=dst_pin_name,
                            type=dst_type
                        ),
                        is_direct=is_direct
                    )
                )

    return connections


# =============================================================================


def build_connections(
        tile_types, tile_grid, switchbox_types, switchbox_grid, clock_cells
):
    """
    Builds a connection map between switchboxes in the grid and between
    switchboxes and underlying tiles.
    """
    connections = []

    # Local and foreign tile connections
    connections += build_tile_connections(
        tile_types, tile_grid, switchbox_types, switchbox_grid
    )

    # HOP connections
    connections += build_hop_connections(switchbox_types, switchbox_grid)

    # GMUX and QMUX connections
    connections += build_gmux_qmux_connections(
        tile_types, tile_grid, switchbox_types, switchbox_grid, clock_cells
    )

    return connections


def check_connections(connections):
    """
    Check if all connections are sane.
     - All connections should be point-to-point. No fanin/fanouts.
    """

    error = False

    # Check if there are no duplicated connections going to the same destination
    dst_conn_locs = set()
    for connection in connections:
        if connection.dst in dst_conn_locs:
            error = True
            print("ERROR: Duplicate destination '{}'".format(connection.dst))
        dst_conn_locs.add(connection.dst)

    # An error ocurred
    assert error is False
