import os.path
import csv
import pickle
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, (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
