import os.path
import csv
import pickle
import pprint
import re
from collections import namedtuple


def read_root_csv(root_dir):
    """ Reads root.csv from raw db directory.

  This should only be used during database generation.

  """
    tiles = {}
    nodes = []

    with open(os.path.join(root_dir, 'root.csv')) as f:
        for d in csv.DictReader(f):
            if d['filetype'] == 'tile':
                if d['subtype'] not in tiles:
                    tiles[d['subtype']] = []

                tiles[d['subtype']].append(
                    os.path.join(root_dir, d['filename']))
            elif d['filetype'] == 'node':
                nodes.append(os.path.join(root_dir, d['filename']))

    return tiles, nodes


def verify_nodes(raw_nodes, nodes, error_nodes):
    """ Compares raw_nodes with generated_nodes and adds errors to error_nodes.

  Args:
    raw_nodes - Iterable of (node name, iterable of wires in node).
    nodes - Iterable of iterable of wires in nodes.
    error_nodes - List to be appended to when an error occurs.  Elements will
                  be 3 tuple of raw node name, raw node, and generated node
                  that did not match.

  """
    wire_nodes = {}
    for node in nodes:
        node_set = set(node)
        for wire in node:
            wire_nodes[wire] = node_set

    for node, raw_node_wires in raw_nodes:
        raw_node_set = set(raw_node_wires)

        for wire in sorted(raw_node_set):
            if wire not in wire_nodes:
                if set((wire, )) != raw_node_set:
                    error_nodes.append((node, tuple(raw_node_set), (wire, )))
            elif wire_nodes[wire] != raw_node_set:
                error_nodes.append((node, tuple(raw_node_set),
                                    tuple(wire_nodes[wire])))


def check_errors(flat_error_nodes, ignored_wires):
    """ Check if error_nodes has errors that are not covered in ignored_wires.

  Args:
    flat_error_nodes - List of error_nodes generated from verify_nodes.
    ignored_wires - List of wires that should be ignored if they were generated.

  """

    error_nodes = {}
    for node, raw_node, generated_nodes in flat_error_nodes:
        if node not in error_nodes:
            error_nodes[node] = {
                'raw_node': set(raw_node),
                'generated_nodes': set(),
            }

        # Make sure all raw nodes are the same.
        assert error_nodes[node]['raw_node'] == set(raw_node)

        error_nodes[node]['generated_nodes'].add(
            tuple(sorted(generated_nodes)))

    for node, error in error_nodes.items():
        combined_generated_nodes = set()
        for generated_node in error['generated_nodes']:
            combined_generated_nodes |= set(generated_node)

        # Make sure there are not extra wires in nodes.
        assert error['raw_node'] == combined_generated_nodes, pprint.pformat((node, error))

        good_node = max(error['generated_nodes'], key=lambda x: len(x))
        bad_nodes = error['generated_nodes'] - set((good_node, ))

        # Max sure only single wires are stranded
        assert max(len(generated_node) for generated_node in bad_nodes) == 1

        for generate_node in bad_nodes:
            for wire in generate_node:
                if wire not in ignored_wires:
                    return False

    return True


class NodeLookup(object):
    def __init__(self):
        self.nodes = {}

    def load_from_nodes(self, nodes):
        self.nodes = nodes

    def load_from_root_csv(self, nodes):
        import pyjson5 as json5
        import progressbar
        for node in progressbar.progressbar(nodes):
            with open(node) as f:
                node_wires = json5.load(f)
                assert node_wires['node'] not in self.nodes
                self.nodes[node_wires['node']] = node_wires['wires']

    def load_from_file(self, fname):
        with open(fname, 'rb') as f:
            self.nodes = pickle.load(f)

    def save_to_file(self, fname):
        with open(fname, 'wb') as f:
            pickle.dump(self.nodes, f)

    def site_pin_node_to_wires(self, tile, node):
        if node is None:
            return

        node_wires = self.nodes[node]

        for wire in node_wires:
            if wire['wire'].startswith(tile + '/'):
                yield wire['wire'][len(tile) + 1:]

    def wires_for_tile(self, tile):
        for node in self.nodes.values():
            for wire in node:
                if wire['wire'].startswith(tile + '/'):
                    yield wire['wire'][len(tile) + 1:]


def compare_prototype_site(proto_a, proto_b):
    """ Compare two proto site type.

  Will assert if prototypes are not equivalent.

  """
    assert proto_a == proto_b, repr((proto_a, proto_b))


# All site names appear to follow the pattern <type>_X<abs coord>Y<abs coord>.
# Generally speaking, only the tile relatively coordinates are required to
# assemble arch defs, so we re-origin the coordinates to be relative to the tile
# (e.g. start at X0Y0) and discard the prefix from the name.
SITE_COORDINATE_PATTERN = re.compile('^(.+)_X([0-9]+)Y([0-9]+)$')

SiteCoordinate = namedtuple('SiteCoordinate', 'prefix x_coord y_coord')


def get_site_coordinate_from_name(name):
    """
    >>> get_site_coordinate_from_name('SLICE_X1Y0')
    SiteCoordinate(prefix='SLICE', x_coord=1, y_coord=0)

    >>> get_site_coordinate_from_name('SLICE_X0Y0')
    SiteCoordinate(prefix='SLICE', x_coord=0, y_coord=0)

    >>> get_site_coordinate_from_name('INT_L_X500Y999')
    SiteCoordinate(prefix='INT_L', x_coord=500, y_coord=999)

    """
    coordinate = SITE_COORDINATE_PATTERN.match(name)
    assert coordinate is not None, name

    return SiteCoordinate(
        prefix=coordinate.group(1),
        x_coord=int(coordinate.group(2)),
        y_coord=int(coordinate.group(3)),
    )


def get_site_prefix_from_name(name):
    """
    Returns the prefix of a site from its name
    """
    coordinate = SITE_COORDINATE_PATTERN.match(name)
    assert coordinate is not None, name

    return coordinate.group(1)


def find_origin_coordinate(site_name, site_names):
    """
    Find the coordinates of each site within the tile, and then subtract the
    smallest coordinate to re-origin them all to be relative to the tile.
    """

    x_coords = []
    y_coords = []
    for site in site_names:
        coordinate = get_site_coordinate_from_name(site)
        site_name_prefix = get_site_prefix_from_name(site_name)
        if coordinate.prefix == site_name_prefix:
            x_coords.append(coordinate.x_coord)
            y_coords.append(coordinate.y_coord)

    if len(x_coords) == 0 or len(y_coords) == 0:
        return 0, 0

    min_x_coord = min(x_coords)
    min_y_coord = min(y_coords)

    return min_x_coord, min_y_coord
