'''

Module that allows to load all the actors and sensors

:author: <NAME>
'''

import os
from GarageDeamon.Common import SensorBase, ActorBase
import operator

class MainLoader(object):

    def __init__(self, base='GarageDeamon.Sensors', base_class=SensorBase):
        self.base = base
        self.baseClass = base_class
        self.pluginNames = None
        self.plugins = {}
        self.reload_plugins()

    def get_plugin_names(self):
        return self.pluginNames

    def get_modules(self):
        return self.plugins

    def get_module(self, name):
        if not self.plugins.get(name, None):
            raise ImportError('No module %s loaded' % name)
        return self.plugins[name]

    def reload_plugins(self):
        self.pluginNames = self._get_plugins()
        self.plugins.clear()
        for module in self.pluginNames:
            mod_name = '%s.%s' % (self.base, module)
            module_tmp = __import__(mod_name, globals(), locals(), [module])
            cls = MainLoader.get_subclass(module_tmp, self.baseClass)
            self.plugins[module] = cls()

    @staticmethod
    def _best_subclass_fit(results):
        subclass_map = {}
        for res in results:
            subclass_map[res] = 0
        for key in subclass_map.keys():
            for res in results:
                try:
                    if issubclass(key, res):
                        subclass_map[key] += 1
                except TypeError:  # If 'obj' is not a class
                    pass
        res = sorted(subclass_map.items(), key=operator.itemgetter(1))
        return res[-1]

    @staticmethod
    def get_subclass(module, base_class):
        good_results = []
        for name in dir(module):
            obj = getattr(module, name)
            if name == base_class.__name__:
                continue
            try:
                if issubclass(obj, base_class):
                    good_results.append(obj)
            except TypeError:  # If 'obj' is not a class
                pass
        if good_results:
            return MainLoader._best_subclass_fit(good_results)[0]
        return None

    @staticmethod
    def convert_to_module_name(name):
        return name.replace('.py', '')

    def _get_plugins(self):
        full_path = os.path.abspath(__file__).split('/')[:-2]
        full_path = '/'.join(full_path)
        full_path = "%s/%s/" % (full_path, self.base.replace('.', '/'))
        modules = []
        for _, _, modules_tmp in os.walk(full_path):
            for module in modules_tmp:
                if not module.endswith('.py'):
                    continue
                if module != '__init__.py' and 'Test' not in module:
                    modules.append(MainLoader.convert_to_module_name(module))
        return modules


SensorLoader = MainLoader()
ActorLoader = MainLoader(base='GarageDeamon.Actors', base_class=ActorBase)

'''

Module that allows to load all the actors and sensors

:author: <NAME>
'''

import os
from GarageDeamon.Common import SensorBase, ActorBase
import operator

class MainLoader(object):

    def __init__(self, base='GarageDeamon.Sensors', base_class=SensorBase):
        self.base = base
        self.baseClass = base_class
        self.pluginNames = None
        self.plugins = {}
        self.reload_plugins()

    def get_plugin_names(self):
        return self.pluginNames

    def get_modules(self):
        return self.plugins

    def get_module(self, name):
        if not self.plugins.get(name, None):
            raise ImportError('No module %s loaded' % name)
        return self.plugins[name]

    def reload_plugins(self):
        self.pluginNames = self._get_plugins()
        self.plugins.clear()
        for module in self.pluginNames:
            mod_name = '%s.%s' % (self.base, module)
            module_tmp = __import__(mod_name, globals(), locals(), [module])
            cls = MainLoader.get_subclass(module_tmp, self.baseClass)
            self.plugins[module] = cls()

    @staticmethod
    def _best_subclass_fit(results):
        subclass_map = {}
        for res in results:
            subclass_map[res] = 0
        for key in subclass_map.keys():
            for res in results:
                try:
                    if issubclass(key, res):
                        subclass_map[key] += 1
                except TypeError:  # If 'obj' is not a class
                    pass
        res = sorted(subclass_map.items(), key=operator.itemgetter(1))
        return res[-1]

    @staticmethod
    def get_subclass(module, base_class):
        good_results = []
        for name in dir(module):
            obj = getattr(module, name)
            if name == base_class.__name__:
                continue
            try:
                if issubclass(obj, base_class):
                    good_results.append(obj)
            except TypeError:  # If 'obj' is not a class
                pass
        if good_results:
            return MainLoader._best_subclass_fit(good_results)[0]
        return None

    @staticmethod
    def convert_to_module_name(name):
        return name.replace('.py', '')

    def _get_plugins(self):
        full_path = os.path.abspath(__file__).split('/')[:-2]
        full_path = '/'.join(full_path)
        full_path = "%s/%s/" % (full_path, self.base.replace('.', '/'))
        modules = []
        for _, _, modules_tmp in os.walk(full_path):
            for module in modules_tmp:
                if not module.endswith('.py'):
                    continue
                if module != '__init__.py' and 'Test' not in module:
                    modules.append(MainLoader.convert_to_module_name(module))
        return modules


SensorLoader = MainLoader()
ActorLoader = MainLoader(base='GarageDeamon.Actors', base_class=ActorBase)

Module that allows to load all the actors and sensors  :author: <NAME> # If 'obj' is not a class # If 'obj' is not a class