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())
