# coding: utf-8

from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

import logging


class SandboxResource(object):
    __slots__ = ('resourceType', 'resourceId', 'taskId', 'taskType')

    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

    def dict(self):
        return {k: str(getattr(self, k)) for k in self.__slots__ if getattr(self, k, None) is not None}


class Layer(object):
    LOGGER = logging.getLogger(__name__)
    __slots__ = ('url', 'fetchable_meta_type', 'resource', 'id', '_rest')

    def __init__(self, url, fetchableMeta, *args, **kwargs):
        self.url = url
        self.fetchable_meta_type = fetchableMeta.get('type', 'SANDBOX_RESOURCE')
        if self.fetchable_meta_type != 'SANDBOX_RESOURCE':
            raise RuntimeError('Unsupported layer resource type')
        else:
            self.resource = SandboxResource(**fetchableMeta['sandboxResource'])

        self._rest = {}
        if kwargs:
            self.LOGGER.warning('Extra kwargs for %s: %s', self, kwargs)
            self._rest.update(kwargs)

    def __eq__(self, other):
        if isinstance(other, Layer):
            return int(self.resource.resourceId) == int(other.resource.resourceId)
        else:
            return NotImplemented

    def _fetchable_meta(self):
        return {'type': self.fetchable_meta_type, 'sandboxResource': self.resource.dict()}

    def __repr__(self):
        return 'Layer(url={}, fetchableMeta={}, {})'.format(
            self.url, self._fetchable_meta(),
            ','.join(['{}={}'.format(k, v) for k, v in self._rest.items()])
        )

    @classmethod
    def from_sandbox_resource(cls, sandbox_resource):
        return cls(
            [sandbox_resource.content_skynet_url],
            {
                'type': 'SANDBOX_RESOURCE',
                'sandboxResource':
                {
                    'resourceType': sandbox_resource.type,
                    'resourceId': sandbox_resource.id,
                    'taskType': sandbox_resource.task.type,
                    'taskId': sandbox_resource.task.id
                }
            }
        )

    def dict(self):
        base = {
            'url': self.url,
            'fetchableMeta': self._fetchable_meta()
        }
        if self._rest:
            base.update(self._rest)
        return base


class LayersConfig(object):
    __slots__ = ('bind', 'layers')

    def __init__(self, bind=None, layer=None):
        self.bind = bind or []
        if layer is None:
            self.layers = []
        else:
            self.layers = [Layer(**layer_dict) for layer_dict in layer]

    def dict(self):
        return {
            'bind': self.bind,
            'layer': [layer.dict() for layer in self.layers]
        }
