import re
import fasm
import bitstream


def mk_fasm(tile_name, feature):
    """ Convert matches tile and feature to FasmLine tuple. """
    # Seperate addressing of multi-bit features:
    # TILE.ALUT[0] -> ('TILE', 'ALUT', '0')
    # TILE.ALUT.SMALL -> ('TILE', 'ALUT.SMALL', None)
    m = re.match(r'([A-Za-z0-9_]+).([^\[]+)(\[[0-9]+\])?', feature)
    tag_post = m.group(2)
    address = None
    if m.group(3) is not None:
        address = int(m.group(3)[1:-1])

    feature = '{}.{}'.format(tile_name, tag_post)

    return fasm.FasmLine(
        set_feature=fasm.SetFasmFeature(
            feature=feature,
            start=address,
            end=None,
            value=1,
            value_format=None,
        ),
        annotations=None,
        comment=None)


class FasmDisassembler(object):
    """ Given a Project X-ray data, outputs FasmLine tuples for bits set. """

    def __init__(self, db):
        self.db = db
        self.grid = self.db.grid()
        self.segment_map = self.grid.get_segment_map()
        self.decode_warnings = set()

    def find_features_in_tile(self,
                              tile_name,
                              block_type,
                              bits,
                              solved_bitdata,
                              bitdata,
                              verbose=False):
        gridinfo = self.grid.gridinfo_at_tilename(tile_name)

        try:
            tile_segbits = self.grid.get_tile_segbits_at_tilename(tile_name)
        except KeyError as e:
            if not verbose:
                return

            if gridinfo.tile_type in self.decode_warnings:
                return

            comment = " WARNING: failed to load DB for tile type {}".format(
                gridinfo.tile_type)
            yield fasm.FasmLine(
                set_feature=None,
                annotations=None,
                comment=comment,
            )
            yield fasm.FasmLine(
                set_feature=None,
                annotations=(
                    fasm.Annotation('missing_segbits', gridinfo.tile_type),
                    fasm.Annotation('exception', str(e)),
                ),
                comment=None,
            )

            self.decode_warnings.add(gridinfo.tile_type)
            return

        for ones_matched, feature in tile_segbits.match_bitdata(
                block_type, bits, bitdata):
            for frame, bit in ones_matched:
                if frame not in solved_bitdata:
                    solved_bitdata[frame] = set()
                solved_bitdata[frame].add(bit)

            yield mk_fasm(tile_name=tile_name, feature=feature)

    def find_features_in_bitstream(self, bitdata, verbose=False):
        solved_bitdata = {}
        frames = set(bitdata.keys())
        tiles_checked = set()

        emitted_features = set()

        while len(frames) > 0:
            frame = frames.pop()

            # Skip frames that were emptied in a previous iteration.
            if not bitdata[frame]:
                continue

            # Iterate over all tiles that use this frame.
            for bits_info in self.segment_map.segment_info_for_frame(frame):
                # Don't examine a tile twice
                if (bits_info.tile, bits_info.block_type) in tiles_checked:
                    continue

                # Check if this frame has any data for the relevant tile.
                any_column = False
                for word_idx in range(bits_info.bits.words):
                    if word_idx + bits_info.bits.offset in bitdata[frame][0]:
                        any_column = True
                        break

                if not any_column:
                    continue

                tiles_checked.add((bits_info.tile, bits_info.block_type))

                for fasm_line in self.find_features_in_tile(
                        bits_info.tile,
                        bits_info.block_type,
                        bits_info.bits,
                        solved_bitdata,
                        bitdata,
                        verbose=verbose):
                    if fasm_line not in emitted_features:
                        emitted_features.add(fasm_line)
                        yield fasm_line

            remaining_bits = bitdata[frame][1]
            if frame in solved_bitdata:
                remaining_bits -= solved_bitdata[frame]

            if len(remaining_bits) > 0 and verbose:
                # Some bits were not decoded, add warning and annotations to
                # FASM.
                yield fasm.FasmLine(
                    set_feature=None,
                    annotations=None,
                    comment=" In frame 0x{:08x} {} bits were not converted.".
                    format(
                        frame,
                        len(remaining_bits),
                    ))

                for bit in remaining_bits:
                    frame_offset = frame % bitstream.FRAME_ALIGNMENT
                    aligned_frame = frame - frame_offset
                    wordidx = bit // bitstream.WORD_SIZE_BITS
                    bitidx = bit % bitstream.WORD_SIZE_BITS

                    annotations = []
                    annotations.append(
                        fasm.Annotation(
                            'unknown_bit', '{:08x}_{}_{}'.format(
                                frame, wordidx, bitidx)))
                    annotations.append(
                        fasm.Annotation('unknown_segment',
                                        '0x{:08x}'.format(aligned_frame)))
                    annotations.append(
                        fasm.Annotation(
                            'unknown_segbit', '{:02d}_{:02d}'.format(
                                frame_offset, bit)))
                    yield fasm.FasmLine(
                        set_feature=None,
                        annotations=tuple(annotations),
                        comment=None,
                    )

    def is_zero_feature(self, feature):
        parts = feature.split('.')
        tile = parts[0]
        gridinfo = self.grid.gridinfo_at_tilename(tile)
        feature = '.'.join(parts[1:])

        db_k = '%s.%s' % (gridinfo.tile_type, feature)
        segbits = self.grid.get_tile_segbits_at_tilename(tile)
        any_bits = False
        for block_type, bit in segbits.feature_to_bits(gridinfo.bits, db_k):
            if bit.isset:
                any_bits = True
                break

        return not any_bits
