import os.path
import simplejson as json
from utils import grid
from utils import tile
from utils import tile_segbits
from utils import site_type
from utils import connections


def get_available_databases(prjxray_root):
    """ Return set of available directory to databases given the root directory
      of prjxray-db
  """
    db_types = set()
    for d in os.listdir(prjxray_root):
        if d.startswith("."):
            continue

        dpath = os.path.join(prjxray_root, d)

        if os.path.exists(os.path.join(dpath, "settings.sh")):
            db_types.add(dpath)

    return db_types


class Database(object):
    def __init__(self, db_root):
        """ Create project x-ray Database at given db_root.

    db_root: Path to directory containing settings.sh, *.db, tilegrid.json and
             tileconn.json

    """
        self.db_root = db_root
        # tilegrid.json JSON object
        self.tilegrid = None
        self.tileconn = None
        self.tile_types = None

        self.tile_types = {}
        self.tile_segbits = {}
        self.site_types = {}

        self.required_features = {}

        for f in os.listdir(self.db_root):
            if f.endswith('.json') and f.startswith('tile_type_'):
                tile_type = f[len('tile_type_'):-len('.json')].lower()

                segbits = os.path.join(
                    self.db_root, 'segbits_{}.db'.format(tile_type))
                if not os.path.isfile(segbits):
                    segbits = None

                block_ram_segbits = os.path.join(
                    self.db_root, 'segbits_{}.block_ram.db'.format(tile_type))
                if not os.path.isfile(block_ram_segbits):
                    block_ram_segbits = None

                ppips = os.path.join(
                    self.db_root, 'ppips_{}.db'.format(tile_type))
                if not os.path.isfile(ppips):
                    ppips = None

                mask = os.path.join(
                    self.db_root, 'mask_{}.db'.format(tile_type))
                if not os.path.isfile(mask):
                    mask = None

                tile_type_file = os.path.join(
                    self.db_root, 'tile_type_{}.json'.format(
                        tile_type.upper()))
                if not os.path.isfile(tile_type_file):
                    tile_type_file = None

                self.tile_types[tile_type.upper()] = tile.TileDbs(
                    segbits=segbits,
                    block_ram_segbits=block_ram_segbits,
                    ppips=ppips,
                    mask=mask,
                    tile_type=tile_type_file,
                )

            if f.endswith('.json') and f.startswith('site_type_'):
                site_type_name = f[len('site_type_'):-len('.json')]

                self.site_types[site_type_name] = os.path.join(self.db_root, f)

            if f.endswith('_required_features.fasm'):
                part = f[:-len('_required_features.fasm')]

                with open(os.path.join(self.db_root, f), "r") as fp:
                    features = []
                    for line in fp:
                        line = line.strip()
                        if len(line) > 0:
                            features.append(line)

                    self.required_features[part] = set(features)

        self.tile_types_obj = {}

    def get_tile_types(self):
        """ Return list of tile types """
        return self.tile_types.keys()

    def get_tile_type(self, tile_type):
        """ Return Tile object for given tilename. """
        if tile_type not in self.tile_types_obj:
            self.tile_types_obj[tile_type] = tile.Tile(
                tile_type, self.tile_types[tile_type])

        return self.tile_types_obj[tile_type]

    def _read_tilegrid(self):
        """ Read tilegrid database if not already read. """
        if not self.tilegrid:
            with open(os.path.join(self.db_root, 'tilegrid.json')) as f:
                self.tilegrid = json.load(f)

    def _read_tileconn(self):
        """ Read tileconn database if not already read. """
        if not self.tileconn:
            with open(os.path.join(self.db_root, 'tileconn.json')) as f:
                self.tileconn = json.load(f)

    def grid(self):
        """ Return Grid object for database. """
        self._read_tilegrid()
        return grid.Grid(self, self.tilegrid)

    def _read_tile_types(self):
        for tile_type, db in self.tile_types.items():
            with open(db.tile_type) as f:
                self.tile_types[tile_type] = json.load(f)

    def connections(self):
        self._read_tilegrid()
        self._read_tileconn()
        self._read_tile_types()

        tile_wires = dict(
            (tile_type, db['wires'])
            for tile_type, db in self.tile_types.items())
        return connections.Connections(
            self.tilegrid, self.tileconn, tile_wires)

    def get_site_types(self):
        return self.site_types.keys()

    def get_site_type(self, site_type_name):
        with open(self.site_types[site_type_name]) as f:
            site_type_data = json.load(f)

        return site_type.SiteType(site_type_data)

    def get_tile_segbits(self, tile_type):
        if tile_type not in self.tile_segbits:
            self.tile_segbits[tile_type] = tile_segbits.TileSegbits(
                self.tile_types[tile_type.upper()])

        return self.tile_segbits[tile_type]

    def get_required_fasm_features(self, part=None):
        """
        Assembles a set of required fasm features for given part. Returns a list
        of fasm features.
        """

        # No required features in the db, return empty list
        if self.required_features is None:
            return set()

        # Return list of part specific features
        return self.required_features.get(part, set())
