# coding: utf-8


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

import logging
from six import string_types
from collections import OrderedDict


class NannyResource(object):
    LOGGER = logging.getLogger(__name__)
    _ISS_PROPERTIES = ('is_dynamic', 'download_speed', 'check_period', 'storage', 'extract_path', 'chksum', )
    __slots__ = ('local_path', ) + _ISS_PROPERTIES

    def __init__(self, local_path, **kwargs):
        self.local_path = local_path
        for iss_property in self._ISS_PROPERTIES:
            value = kwargs.pop(iss_property, None)
            if isinstance(value, string_types) and value.isspace() or value == '0d0h0m':
                self.LOGGER.debug('Dropping insignificant value %s of %s', value, iss_property)
                setattr(self, iss_property, None)
            else:
                setattr(self, iss_property, value)

        if kwargs:
            self.LOGGER.warning('Extra keys %s for NannyResource', kwargs)

    def dict(self):
        all_slots = [s for s in self.__slots__]
        mro = type(self).mro()
        for next_class in mro[mro.index(self.__class__) + 1:]:
            if hasattr(next_class, '__slots__'):
                all_slots.extend([s for s in next_class.__slots__])
        raw_dict = {k: getattr(self, k) for k in all_slots if getattr(self, k) is not None}
        result_dict = {}
        for k, v in raw_dict.items():
            if k in ('resource_id', 'task_id') and not isinstance(v, string_types):
                result_dict[k] = str(v)
            else:
                result_dict[k] = v
        return result_dict

    def __repr__(self):
        return '{}({})'.format(self.__class__.__name__, self.dict())


class SandboxFile(NannyResource):
    RESOURCES_DICT_KEY = 'sandbox_files'
    __slots__ = ('task_type', 'task_id', 'resource_type', 'resource_id', )

    def __init__(self, local_path, task_type, task_id, resource_type, resource_id=None, **kwargs):
        super(SandboxFile, self).__init__(local_path, **kwargs)
        self.task_type = task_type
        self.task_id = task_id
        self.resource_type = resource_type
        self.resource_id = resource_id

    def __eq__(self, other):
        if isinstance(other, SandboxFile):
            return self.local_path == other.local_path and self.task_id == other.task_id and self.resource_type == other.resource_type
        else:
            return NotImplemented

    def __hash__(self):
        return hash((self.local_path, self.task_id, self.resource_type, self.resource_id))

    @classmethod
    def from_sandbox_resource(cls, local_path, sandbox_resource):
        return cls(
            local_path,
            resource_type=sandbox_resource.type,
            resource_id=sandbox_resource.id,
            task_type=sandbox_resource.task.type,
            task_id=sandbox_resource.task.id
        )


class StaticFile(NannyResource):
    RESOURCES_DICT_KEY = 'static_files'
    __slots__ = ('content', )

    def __init__(self, local_path, content, **kwargs):
        super(StaticFile, self).__init__(local_path, **kwargs)
        self.content = content

    def __eq__(self, other):
        if isinstance(other, StaticFile):
            return self.local_path == other.local_path and self.content == other.content
        else:
            return NotImplemented

    def __hash__(self):
        return hash((self.local_path, self.content))


class UrlFile(NannyResource):
    RESOURCES_DICT_KEY = 'url_files'
    __slots__ = ('url', )

    def __init__(self, local_path, url, **kwargs):
        super(UrlFile, self).__init__(local_path, **kwargs)
        self.url = url

    def __eq__(self, other):
        if isinstance(other, UrlFile):
            return self.local_path == other.local_path and self.url == other.url
        else:
            return NotImplemented

    def __hash__(self):
        return hash((self.local_path, self.url))


class TemplateSetFile(NannyResource):
    RESOURCES_DICT_KEY = 'template_set_files'
    __slots__ = ('templates', 'layout', )

    def __init__(self, local_path, templates, layout, **kwargs):
        super(TemplateSetFile, self).__init__(local_path, **kwargs)
        self.layout = layout
        self.templates = OrderedDict()
        for template in templates:
            self.templates[template['name']] = template['content']

    def __eq__(self, other):
        if isinstance(other, TemplateSetFile):
            return self.local_path == other.local_path and self.templates == other.templates and self.layout == other.layout
        else:
            return NotImplemented

    def __hash__(self):
        return hash((self.local_path, self.layout, tuple(sorted(self.templates.items()))))

    def dict(self):
        base_dict = super(TemplateSetFile, self).dict()
        base_dict['templates'] = [{'name': v[0], 'content': v[1]} for v in self.templates.items()]
        return base_dict
