# Path: plex/objects/core/base.py
# class Property(object):
#     helpers = Interface.helpers
# 
#     def __init__(self, name=None, type=None, resolver=None):
#         self.name = name
#         self.type = type
#         self.resolver = resolver
# 
#     def value(self, descriptor, client, key, node, keys_used):
#         if self.resolver is not None:
#             return self.value_func(descriptor, client, key, node, keys_used)
# 
#         return self.value_node(descriptor, key, node, keys_used)
# 
#     def value_node(self, descriptor, key, node, keys_used):
#         value = self.helpers.get(node, key)
# 
#         if value is None:
#             return None
# 
#         keys_used.append(key.lower())
# 
#         try:
#             return self.value_convert(value)
#         except Exception as ex:
#             log.warn('[%s] Unable to parse property %r - %%s' % (descriptor.__name__, key), ex, exc_info=True)
#             return None
# 
#     def value_convert(self, value):
#         if not self.type:
#             return value
# 
#         types = self.type if isinstance(self.type, collections.Iterable) else [self.type]
#         result = value
# 
#         for target_type in types:
#             try:
#                 result = target_type(result)
#             except Exception as ex:
#                 six.reraise(ex, None, sys.exc_info()[2])
# 
#         return result
# 
#     def value_func(self, descriptor, client, key, node, keys_used):
#         func = self.resolver()
# 
#         try:
#             keys, value = func(client, node)
# 
#             keys_used.extend([k.lower() for k in keys])
#             return value
#         except Exception as ex:
#             log.warn('[%s] Exception raised in value function for %r - %%s' % (descriptor.__name__, key), ex, exc_info=True)
#             return None
# 
# Path: plex/objects/container.py
# class Container(Descriptor):
#     size = Property(type=int)
# 
#     updated_at = Property('updatedAt', int)
# 
#     def first(self):
#         for item in self:
#             return item
# 
# Path: plex/objects/library/section.py
# class Section(Directory):
#     uuid = Property
# 
#     filters = Property(type=bool)
#     refreshing = Property(type=bool)
# 
#     agent = Property
#     scanner = Property
#     language = Property
# 
#     composite = Property
# 
#     created_at = Property('createdAt', int)
# 
#     def __transform__(self):
#         self.path = '/library/sections/%s' % self.key
# 
#     def all(self):
#         response = self.http.get('all')
# 
#         return self.parse(response, idict({
#             'MediaContainer': ('MediaContainer', idict({
#                 'Directory': {
#                     'artist':   'Artist',
#                     'show':     'Show'
#                 },
#                 'Photo': {
#                     'photo':    'Photo'
#                 },
#                 'Video': {
#                     'movie':    'Movie'
#                 }
#             }))
#         }))


from plex.core.helpers import flatten, to_iterable
from plex.objects.core.base import Property
from plex.objects.container import Container
from plex.objects.library.section import Section

class ChildrenContainer(MediaContainer):
    pass


class LeavesContainer(MediaContainer):
    pass


class SectionContainer(MediaContainer):
    filter_passes = lambda _, allowed, value: allowed is None or value in allowed

    def filter(self, types=None, keys=None, titles=None):
        types = to_iterable(types)
        keys = to_iterable(keys)

        titles = to_iterable(titles)

        if titles:
            # Flatten titles
            titles = [flatten(x) for x in titles]

        for section in self:
            if not self.filter_passes(types, section.type):
                continue

            if not self.filter_passes(keys, section.key):
                continue

            if not self.filter_passes(titles, flatten(section.title)):

# Path: plex/objects/core/base.py
# class Property(object):
#     helpers = Interface.helpers
# 
#     def __init__(self, name=None, type=None, resolver=None):
#         self.name = name
#         self.type = type
#         self.resolver = resolver
# 
#     def value(self, descriptor, client, key, node, keys_used):
#         if self.resolver is not None:
#             return self.value_func(descriptor, client, key, node, keys_used)
# 
#         return self.value_node(descriptor, key, node, keys_used)
# 
#     def value_node(self, descriptor, key, node, keys_used):
#         value = self.helpers.get(node, key)
# 
#         if value is None:
#             return None
# 
#         keys_used.append(key.lower())
# 
#         try:
#             return self.value_convert(value)
#         except Exception as ex:
#             log.warn('[%s] Unable to parse property %r - %%s' % (descriptor.__name__, key), ex, exc_info=True)
#             return None
# 
#     def value_convert(self, value):
#         if not self.type:
#             return value
# 
#         types = self.type if isinstance(self.type, collections.Iterable) else [self.type]
#         result = value
# 
#         for target_type in types:
#             try:
#                 result = target_type(result)
#             except Exception as ex:
#                 six.reraise(ex, None, sys.exc_info()[2])
# 
#         return result
# 
#     def value_func(self, descriptor, client, key, node, keys_used):
#         func = self.resolver()
# 
#         try:
#             keys, value = func(client, node)
# 
#             keys_used.extend([k.lower() for k in keys])
#             return value
#         except Exception as ex:
#             log.warn('[%s] Exception raised in value function for %r - %%s' % (descriptor.__name__, key), ex, exc_info=True)
#             return None
# 
# Path: plex/objects/container.py
# class Container(Descriptor):
#     size = Property(type=int)
# 
#     updated_at = Property('updatedAt', int)
# 
#     def first(self):
#         for item in self:
#             return item
# 
# Path: plex/objects/library/section.py
# class Section(Directory):
#     uuid = Property
# 
#     filters = Property(type=bool)
#     refreshing = Property(type=bool)
# 
#     agent = Property
#     scanner = Property
#     language = Property
# 
#     composite = Property
# 
#     created_at = Property('createdAt', int)
# 
#     def __transform__(self):
#         self.path = '/library/sections/%s' % self.key
# 
#     def all(self):
#         response = self.http.get('all')
# 
#         return self.parse(response, idict({
#             'MediaContainer': ('MediaContainer', idict({
#                 'Directory': {
#                     'artist':   'Artist',
#                     'show':     'Show'
#                 },
#                 'Photo': {
#                     'photo':    'Photo'
#                 },
#                 'Video': {
#                     'movie':    'Movie'
#                 }
#             }))
#         }))


# Path: plex/objects/library/container.py
from plex.core.helpers import flatten, to_iterable
from plex.objects.core.base import Property
from plex.objects.container import Container
from plex.objects.library.section import Section


class ChildrenContainer(MediaContainer):
    pass


class LeavesContainer(MediaContainer):
    pass


class SectionContainer(MediaContainer):
    filter_passes = lambda _, allowed, value: allowed is None or value in allowed

    def filter(self, types=None, keys=None, titles=None):
        types = to_iterable(types)
        keys = to_iterable(keys)

        titles = to_iterable(titles)

        if titles:
            # Flatten titles
            titles = [flatten(x) for x in titles]

        for section in self:
            if not self.filter_passes(types, section.type):
                continue

            if not self.filter_passes(keys, section.key):
                continue

            if not self.filter_passes(titles, flatten(section.title)):

                continue