""" TileSegbitsAlias provides an alias from one tile type to another.

TileSegbitsAlias performs severals functions to achieve the alias:
 - Remaps tile type from the original tile type to the alias tile type
 - Offsets the bits from the original to the alias type
 - Renames sites from the original to the alias type
 - Filters bits outside of the alias.


"""

from utils import bitstream
from utils.grid_types import Bits
from utils.tile_segbits import read_ppips


class TileSegbitsAlias(object):
    def __init__(self, db, tile_type, bits_map):
        # Name of tile_type that is using the alias
        self.tile_type = tile_type

        # Name of aliased tile_type
        self.alias_tile_type = None

        # BlockType -> BitAlias map
        self.alias = {}

        self.bits_map = bits_map

        # BlockType -> aliased Bits map
        self.alias_bits_map = {}

        # aliased site name to site name map
        self.sites_rev_map = {}

        for block_type in bits_map:
            self.alias[block_type] = bits_map[block_type].alias
            self.alias_bits_map[block_type] = Bits(
                base_address=bits_map[block_type].base_address,
                frames=bits_map[block_type].frames,
                offset=bits_map[block_type].offset -
                self.alias[block_type].start_offset,
                words=bits_map[block_type].words,
                alias=None,
            )

            if self.alias_tile_type is None:
                self.alias_tile_type = self.alias[block_type].tile_type
            else:
                assert self.alias_tile_type == self.alias[block_type].tile_type

            self.sites_rev_map[block_type] = {}
            for site, alias_site in self.alias[block_type].sites.items():
                assert alias_site not in self.sites_rev_map[block_type]
                self.sites_rev_map[block_type][alias_site] = site

        tile_db = db.tile_types[self.tile_type]
        self.ppips = {}

        if tile_db.ppips is not None:
            with open(tile_db.ppips) as f:
                self.ppips = read_ppips(f)
        self.tile_segbits = db.get_tile_segbits(self.alias_tile_type)

    def map_feature_to_segbits(self, feature):
        """ Map from the output feature name to the aliased feature name. """
        parts = feature.split('.')

        assert parts[0] == self.tile_type
        parts[0] = self.alias_tile_type

        for block_type in self.alias:
            if len(parts) > 1 and parts[1] in self.alias[block_type].sites:
                parts[1] = self.alias[block_type].sites[parts[1]]

        return '.'.join(parts)

    def map_feature_from_segbits(self, feature):
        """ Map from the aliases feature name to the output feature name. """
        parts = feature.split('.')

        assert parts[0] == self.alias_tile_type
        parts[0] = self.tile_type

        for block_type in self.alias:
            if len(parts) > 1 and parts[1] in self.sites_rev_map[block_type]:
                parts[1] = self.sites_rev_map[block_type][parts[1]]

        return '.'.join(parts)

    def match_filter(self, block_type, query_bit):
        word = query_bit.word_bit // bitstream.WORD_SIZE_BITS
        real_word = word - self.alias[block_type].start_offset
        if real_word < 0 or real_word >= self.bits_map[block_type].words:
            return False

        return True

    def match_bitdata(self, block_type, bits, bitdata):
        alias_bits = self.alias_bits_map[block_type]

        for bits_found, alias_feature in self.tile_segbits.match_bitdata(
                block_type, alias_bits, bitdata,
                match_filter=self.match_filter):
            feature = self.map_feature_from_segbits(alias_feature)

            yield (bits_found, feature)

    def feature_to_bits(self, bits_map, feature, address=0):
        if feature in self.ppips:
            return

        alias_feature = self.map_feature_to_segbits(feature)
        for block_type, bit in self.tile_segbits.feature_to_bits(
                self.alias_bits_map, alias_feature, address):
            yield block_type, bit
