from utils import segment_map
from utils.grid_types import BlockType, GridLoc, GridInfo, BitAlias, Bits, BitsInfo, ClockRegion
from utils.tile_segbits_alias import TileSegbitsAlias
import re

CLOCK_REGION_RE = re.compile('X([0-9])Y([0-9])')


class Grid(object):
    """ Object that represents grid for a given database.

  Provides methods to inspect grid by name or location.  Also provides mapping
  of segment offsets for particular grid locations and their tile types.
  """

    def __init__(self, db, tilegrid):
        self.db = db
        self.tilegrid = tilegrid
        self.loc = {}
        self.tileinfo = {}

        clock_regions = {}

        for tile in self.tilegrid:
            tileinfo = self.tilegrid[tile]
            grid_loc = GridLoc(tileinfo['grid_x'], tileinfo['grid_y'])
            assert grid_loc not in self.loc
            self.loc[grid_loc] = tile

            bits = {}

            if 'bits' in tileinfo:
                for k in tileinfo['bits']:
                    segment_type = BlockType(k)
                    base_address = int(tileinfo['bits'][k]['baseaddr'], 0)

                    alias = None
                    if 'alias' in tileinfo['bits'][k]:
                        alias = BitAlias(
                            tile_type=tileinfo['bits'][k]['alias']['type'],
                            start_offset=tileinfo['bits'][k]['alias']
                            ['start_offset'],
                            sites=tileinfo['bits'][k]['alias']['sites'],
                        )

                    bits[segment_type] = Bits(
                        base_address=base_address,
                        frames=tileinfo['bits'][k]['frames'],
                        offset=tileinfo['bits'][k]['offset'],
                        words=tileinfo['bits'][k]['words'],
                        alias=alias,
                    )

            clock_region = None
            if 'clock_region' in tileinfo:
                if tileinfo['clock_region'] is not None:
                    if tileinfo['clock_region'] not in clock_regions:
                        m = CLOCK_REGION_RE.fullmatch(tileinfo['clock_region'])
                        assert m is not None, tileinfo['clock_region']

                        clock_regions[tileinfo['clock_region']] = ClockRegion(
                            name=tileinfo['clock_region'],
                            x=int(m.group(1)),
                            y=int(m.group(2)))

                    clock_region = clock_regions[tileinfo['clock_region']]

            self.tileinfo[tile] = GridInfo(
                bits=bits,
                sites=tileinfo['sites'],
                tile_type=tileinfo['type'],
                pin_functions=tileinfo.get('pin_functions', {}),
                clock_region=clock_region,
            )

        x, y = zip(*self.loc.keys())
        self._dims = (min(x), max(x), min(y), max(y))

    def tiles(self):
        """ Return list of tiles. """
        return self.tileinfo.keys()

    def tile_locations(self):
        """ Return list of tile locations. """
        return self.loc.keys()

    def dims(self):
        """ Returns (x_min, x_max, y_min, y_max) for given Grid. """
        return self._dims

    def is_populated(self, grid_loc):
        return grid_loc in self.loc

    def loc_of_tilename(self, tilename):
        tileinfo = self.tilegrid[tilename]
        return GridLoc(tileinfo['grid_x'], tileinfo['grid_y'])

    def tilename_at_loc(self, grid_loc):
        return self.loc[grid_loc]

    def gridinfo_at_loc(self, grid_loc):
        return self.tileinfo[self.loc[grid_loc]]

    def gridinfo_at_tilename(self, tilename):
        return self.tileinfo[tilename]

    def iter_all_frames(self):
        for tile, tileinfo in self.tileinfo.items():
            for block_type, bits in tileinfo.bits.items():
                yield BitsInfo(
                    block_type=block_type,
                    tile=tile,
                    bits=bits,
                )

    def get_segment_map(self):
        return segment_map.SegmentMap(self)

    def tile_key(self, tilename):
        gridinfo = self.gridinfo_at_tilename(tilename)
        loc = self.loc_of_tilename(tilename)
        tile_type = gridinfo.tile_type

        return (tile_type, loc.grid_x, -loc.grid_y)

    def get_tile_segbits_at_tilename(self, tilename):
        gridinfo = self.gridinfo_at_tilename(tilename)

        # Check to see if alias is present
        any_alias = False
        for block_type, bits in gridinfo.bits.items():
            if bits.alias is not None:
                any_alias = True

        if any_alias:
            return TileSegbitsAlias(self.db, gridinfo.tile_type, gridinfo.bits)
        else:
            return self.db.get_tile_segbits(gridinfo.tile_type)
