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, part):
        """ 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
        self.part = part
        # 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)

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

                self.required_features[self.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, self.part,
                                   '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, self.part,
                                   '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())
