import re
import six
from syncano import logger
class Registry(object):
    """Models registry.
[docs]    """
    def __init__(self, models=None):
        self.models = models or {}
        self.schemas = {}
        self.patterns = []
        self._pending_lookups = {}
        self.instance_name = None
        self._default_connection = None
    def __str__(self):
        return 'Registry: {0}'.format(', '.join(self.models))
    def __unicode__(self):
        return six.u(str(self))
    def __iter__(self):
        for name, model in six.iteritems(self.models):
            yield model
    def get_model_patterns(self, cls):
        patterns = []
[docs]        for k, v in six.iteritems(cls._meta.endpoints):
            pattern = '^{0}$'.format(v['path'])
            for name in v.get('properties', []):
                pattern = pattern.replace('{{{0}}}'.format(name), '([^/.]+)')
            patterns.append((re.compile(pattern), cls))
        return patterns
    def get_model_by_path(self, path):
        for pattern, cls in self.patterns: 
[docs]            if pattern.match(path):
                return cls
        raise LookupError('Invalid path: {0}'.format(path))
    def get_model_by_name(self, name):
        return self.models[name] 
[docs]
    def update(self, name, cls):
        self.models[name] = cls 
[docs]        related_name = cls._meta.related_name
        patterns = self.get_model_patterns(cls)
        self.patterns.extend(patterns)
        setattr(self, str(name), cls)
        setattr(self, str(related_name), cls.please.all())
        logger.debug('New model: %s, %s', name, related_name)
    def add(self, name, cls):
 
[docs]        if name not in self.models:
            self.update(name, cls)
        if name in self._pending_lookups:
            lookups = self._pending_lookups.pop(name)
            for callback, args, kwargs in lookups:
                callback(*args, **kwargs)
        return self
    def set_default_property(self, name, value):
        for model in self: 
[docs]            if name not in model.__dict__:
                continue
            for field in model._meta.fields:
                if field.name == name:
                    field.default = value
    def set_default_instance(self, value):
        self.set_default_property('instance_name', value) 
[docs]
    def set_used_instance(self, instance):
        if instance and self.instance_name != instance or registry.instance_name is None: 
[docs]            self.set_default_instance(instance)  # update the registry with last used instance;
            self.instance_name = instance
    def clear_used_instance(self):
        self.instance_name = None 
[docs]        self.set_default_instance(None)
    def get_schema(self, class_name):
        return self.schemas.get(class_name) 
[docs]
    def set_schema(self, class_name, schema):
        self.schemas[class_name] = schema 
[docs]
    def clear_schemas(self):
        self.schemas = {} 
[docs]
    def set_default_connection(self, default_connection):
        self._default_connection = default_connection 
[docs]
    @property
    def connection(self): 
        if not self._default_connection:
[docs]            raise Exception('Set the default connection first.')
        return self._default_connection
registry = Registry()