# Path: resources/lib/routing/route.py
# class Route(yaml.YAMLObject):
#     """Symbolic base class for routes"""
#     yaml_tag = u'!route'
# 
#     def __init__(self, service_name, class_name, service, prefix):
#         self.service_name = service_name
#         self.class_name = class_name
#         self.service = service
#         self.prefix = prefix
#         self.is_main_route = (prefix == 'main')
# 
#     @classmethod
#     def from_dict(cls, service_name=None, class_name=None, service=None, prefix=None, **kwargs):
#         return cls(service_name, class_name, service, prefix)
# 
# Path: resources/lib/di/requiredfeature.py
# class RequiredFeature(object):
#     def __init__(self, feature, assertion=featurebroker.no_assertion):
#         self.feature = feature
#         self.assertion = assertion
# 
#     def __get__(self, instance, owner):
#         return self.result
# 
#     def __getattr__(self, name):
#         assert name == 'result', "Unexpected attribute request other than 'result': %s" % name
#         self.result = self.request()
#         return self.result
# 
#     def _build_attributes_dict(self, class_, feature):
#         args = getattr(feature, 'arguments', None)
#         if args is not None:
#             for index, arg in enumerate(feature.arguments):
#                 # TODO: checking for instance is generally a bad idea and only a temporary workaround to allow
#                 # eos-helper's functionality
#                 if isinstance(arg, str) and arg[:1] == '@':
#                     feature.arguments[index] = RequiredFeature(arg[1:]).request()
#             args = inspect.getargspec(class_.__init__)[0]
#             if args[0] == 'self':
#                 args.pop(0)
#             argument_dict = dict(zip(args, feature.arguments))
# 
#             return argument_dict
#         else:
#             return None
# 
#     def request(self):
#         if featurebroker.features.get_initialized(self.feature) is not None:
#             instance = featurebroker.features.get_initialized(self.feature)
#         else:
#             feature = featurebroker.features[self.feature]
# 
#             lazy = getattr(feature, 'lazy', None)
#             if lazy is not None:
#                 lazy_module = importlib.import_module('resources.lib.di.lazyproxy')
#                 lazy_class = getattr(lazy_module, 'LazyProxy')
# 
#                 lazy_instance = lazy_class(
#                     original_module=feature.module,
#                     original_class=feature.class_name,
#                     init_args=feature.arguments
#                 )
# 
#                 featurebroker.features.set_initialized(self.feature, lazy_instance)
# 
#                 return lazy_instance
# 
#             module = importlib.import_module(feature.module)
#             class_ = getattr(module, feature.class_name)
# 
#             factory = getattr(feature, 'factory_class', None)
#             if factory is not None:
#                 factory_class = RequiredFeature(feature.factory_class[1:]).request()
#                 factory_method = feature.factory_method
# 
#                 if featurebroker.has_methods(factory_method)(factory_class):
#                     arguments = self._build_attributes_dict(class_, feature)
#                     if arguments is not None:
#                         instance = getattr(factory_class, factory_method)(**arguments)
#                     else:
#                         instance = getattr(factory_class, factory_method)()
# 
#             else:
#                 arguments = self._build_attributes_dict(class_, feature)
#                 if arguments is not None:
#                     instance = class_(**arguments)
#                 else:
#                     instance = class_()
#                 assert self.assertion(instance), \
#                     "The value %s of %r does not match the specified criteria" \
#                     % (instance, self.feature)
# 
#             try:
#                 tagged_features = featurebroker.features.get_tagged_features(self.feature)
#                 if featurebroker.has_methods('append')(instance):
#                     for key, tagged_feature in enumerate(tagged_features):
#                         tagged_features[key] = RequiredFeature(tagged_feature.name).request()
# 
#                     instance.append(tagged_features)
#             except KeyError:
#                 pass
# 
#             featurebroker.features.set_initialized(self.feature, instance)
# 
#             if hasattr(feature, 'calls') and feature.calls is not None:
#                 for call in feature.calls:
#                     method = call[0]
#                     args = call[1]
# 
#                     for key, arg in enumerate(args):
#                         if arg[:1] == '@':
#                             if featurebroker.features.get_initialized(arg[:1]) is not None:
#                                 args[key] = featurebroker.features.get_initialized(arg[:1])
# 
#                     resolved_all_services = True
#                     for key, arg in enumerate(args):
#                         if isinstance(arg, str) and arg[:1] == '@':
#                             resolved_all_services = False
# 
#                     if resolved_all_services:
#                         method(instance, **args)
# 
#         return instance


import os
import sys
import yaml
import xbmc
import xbmcaddon
from resources.lib.routing.route import Route
from resources.lib.di.requiredfeature import RequiredFeature
    def register(self, cls):
        route = self.routing[cls.__name__]
        routes_cache = {}
        for key, value in self._routes_cache.iteritems():
            xbmc.log('[script.luna.router]: Added Route: %s_%s -> %s' % (route.prefix, key, value))
            routes_cache["%s_%s" % (route.prefix, key)] = value
        self.routes.update(routes_cache)
        self._routes_cache = {}
        return cls

    """
    def route(self, name):
        def decorator(func):
            xbmc.log("[script.luna.router]: Adding route with name %s" % name)
            self._routes_cache[name] = func
            return func
        return decorator
    """

    def render(self, name, instance=None, args=None):
        try:
            # TODO: splitting at the first occurrence isn't the best idea ...
            # TODO: are duplicate prefixes on different controllers a possible use case?
            route = None
            prefix = name.split('_')[0]
            for key, _route in self.routing.iteritems():
                if _route.prefix == prefix:
                    route = _route
            # TODO: if we need to refactor this, call Dennis
            if route is not None:

# Path: resources/lib/routing/route.py
# class Route(yaml.YAMLObject):
#     """Symbolic base class for routes"""
#     yaml_tag = u'!route'
# 
#     def __init__(self, service_name, class_name, service, prefix):
#         self.service_name = service_name
#         self.class_name = class_name
#         self.service = service
#         self.prefix = prefix
#         self.is_main_route = (prefix == 'main')
# 
#     @classmethod
#     def from_dict(cls, service_name=None, class_name=None, service=None, prefix=None, **kwargs):
#         return cls(service_name, class_name, service, prefix)
# 
# Path: resources/lib/di/requiredfeature.py
# class RequiredFeature(object):
#     def __init__(self, feature, assertion=featurebroker.no_assertion):
#         self.feature = feature
#         self.assertion = assertion
# 
#     def __get__(self, instance, owner):
#         return self.result
# 
#     def __getattr__(self, name):
#         assert name == 'result', "Unexpected attribute request other than 'result': %s" % name
#         self.result = self.request()
#         return self.result
# 
#     def _build_attributes_dict(self, class_, feature):
#         args = getattr(feature, 'arguments', None)
#         if args is not None:
#             for index, arg in enumerate(feature.arguments):
#                 # TODO: checking for instance is generally a bad idea and only a temporary workaround to allow
#                 # eos-helper's functionality
#                 if isinstance(arg, str) and arg[:1] == '@':
#                     feature.arguments[index] = RequiredFeature(arg[1:]).request()
#             args = inspect.getargspec(class_.__init__)[0]
#             if args[0] == 'self':
#                 args.pop(0)
#             argument_dict = dict(zip(args, feature.arguments))
# 
#             return argument_dict
#         else:
#             return None
# 
#     def request(self):
#         if featurebroker.features.get_initialized(self.feature) is not None:
#             instance = featurebroker.features.get_initialized(self.feature)
#         else:
#             feature = featurebroker.features[self.feature]
# 
#             lazy = getattr(feature, 'lazy', None)
#             if lazy is not None:
#                 lazy_module = importlib.import_module('resources.lib.di.lazyproxy')
#                 lazy_class = getattr(lazy_module, 'LazyProxy')
# 
#                 lazy_instance = lazy_class(
#                     original_module=feature.module,
#                     original_class=feature.class_name,
#                     init_args=feature.arguments
#                 )
# 
#                 featurebroker.features.set_initialized(self.feature, lazy_instance)
# 
#                 return lazy_instance
# 
#             module = importlib.import_module(feature.module)
#             class_ = getattr(module, feature.class_name)
# 
#             factory = getattr(feature, 'factory_class', None)
#             if factory is not None:
#                 factory_class = RequiredFeature(feature.factory_class[1:]).request()
#                 factory_method = feature.factory_method
# 
#                 if featurebroker.has_methods(factory_method)(factory_class):
#                     arguments = self._build_attributes_dict(class_, feature)
#                     if arguments is not None:
#                         instance = getattr(factory_class, factory_method)(**arguments)
#                     else:
#                         instance = getattr(factory_class, factory_method)()
# 
#             else:
#                 arguments = self._build_attributes_dict(class_, feature)
#                 if arguments is not None:
#                     instance = class_(**arguments)
#                 else:
#                     instance = class_()
#                 assert self.assertion(instance), \
#                     "The value %s of %r does not match the specified criteria" \
#                     % (instance, self.feature)
# 
#             try:
#                 tagged_features = featurebroker.features.get_tagged_features(self.feature)
#                 if featurebroker.has_methods('append')(instance):
#                     for key, tagged_feature in enumerate(tagged_features):
#                         tagged_features[key] = RequiredFeature(tagged_feature.name).request()
# 
#                     instance.append(tagged_features)
#             except KeyError:
#                 pass
# 
#             featurebroker.features.set_initialized(self.feature, instance)
# 
#             if hasattr(feature, 'calls') and feature.calls is not None:
#                 for call in feature.calls:
#                     method = call[0]
#                     args = call[1]
# 
#                     for key, arg in enumerate(args):
#                         if arg[:1] == '@':
#                             if featurebroker.features.get_initialized(arg[:1]) is not None:
#                                 args[key] = featurebroker.features.get_initialized(arg[:1])
# 
#                     resolved_all_services = True
#                     for key, arg in enumerate(args):
#                         if isinstance(arg, str) and arg[:1] == '@':
#                             resolved_all_services = False
# 
#                     if resolved_all_services:
#                         method(instance, **args)
# 
#         return instance


# Path: resources/lib/routing/router.py
import os
import sys
import yaml
import xbmc
import xbmcaddon
from resources.lib.routing.route import Route
from resources.lib.di.requiredfeature import RequiredFeature

    def register(self, cls):
        route = self.routing[cls.__name__]
        routes_cache = {}
        for key, value in self._routes_cache.iteritems():
            xbmc.log('[script.luna.router]: Added Route: %s_%s -> %s' % (route.prefix, key, value))
            routes_cache["%s_%s" % (route.prefix, key)] = value
        self.routes.update(routes_cache)
        self._routes_cache = {}
        return cls

    """
    def route(self, name):
        def decorator(func):
            xbmc.log("[script.luna.router]: Adding route with name %s" % name)
            self._routes_cache[name] = func
            return func
        return decorator
    """

    def render(self, name, instance=None, args=None):
        try:
            # TODO: splitting at the first occurrence isn't the best idea ...
            # TODO: are duplicate prefixes on different controllers a possible use case?
            route = None
            prefix = name.split('_')[0]
            for key, _route in self.routing.iteritems():
                if _route.prefix == prefix:
                    route = _route
            # TODO: if we need to refactor this, call Dennis
            if route is not None:

                instance = RequiredFeature(route.service[1:]).request()