#python
import logging
from copy import copy
from StringIO import StringIO

#zope
from Acquisition import aq_parent
from zope import component
try:
    from zope.component.hooks import getSite
except ImportError:
    #BBB
    from zope.site.hooks import getSite
from Products.Five import BrowserView

#CMF
from Products.CMFCore.utils import getToolByName
from Products.ResourceRegistries.tools.packer import CSSPacker
from Products.ResourceRegistries.tools.packer import JavascriptPacker
from Products.ResourceRegistries.utils import applyPrefix

#plone
from plone.registry.interfaces import IRegistry
from plone.app.jqueryui import interfaces, config

logger = logging.getLogger('plone.app.jqueryui')


class Resources(BrowserView):
    _key = None
    _header_template = u"\n/* plone.app.jqueryui: %s */\n"
    _mimetype = None
    _tool = None
    _toolid = None
    _packer = None
    _js = False
    _css = False

    @property
    def tool(self):
        if self._tool is None:
            if self._toolid:
                self._tool = getToolByName(self.context,
                                           self._toolid)
            else:
                self._tool = False
        return self._tool

    @property
    def debug(self):
        ret = False
        if self.tool:
            ret = self.tool.getDebugMode()
        return ret

    def settings(self):
        """Return records from portal_registry corresponding to
        IJQueryUIPlugins
        """
        registry = component.queryUtility(IRegistry)
        if registry is None or self._key is None:
            return
        return registry.forInterface(self._key, None)

    def __call__(self):
        settings = self.settings
        if settings is None:
            return
        resources = self.get_resources()
        if not resources:
            return
        if self._mimetype:
            self.request.response.setHeader('Content-Type',
                                            self._mimetype)
        return self.get_resources_content(resources)

    def pack(self, content):
        if self._packer and not self.debug:
            return self._packer('safe').pack(content)
        return content

    def get_resources_content(self, resources):
        """Resources must be a list of resource ids.
        This method return the content of each resources appended in one string
        """
        data = StringIO()
        if resources is None:
            resources = self.get_resources()
        upath = self.context.absolute_url_path()
        for resourceid in resources:
            try:
                resource = self.context.restrictedTraverse(
                    resourceid)
            except KeyError, e:
                logger.error(e)
                continue
            if not resource:
                continue
            if self._header_template:
                data.write(
                    self._header_template % (
                        resource.context.__name__
                    )
                )
                data.write(u"\n")
                fic = open(resource.context.path, 'r')
                content = fic.read()
                fic.close()
                try:
                    content = unicode(content)

                except Exception, e:
                    content = unicode(
                        content.decode('utf-8'))
                if self._css:
                    upath = upath.rstrip('/')
                    prefix = '/'.join([upath, resourceid])
                    if prefix.endswith('/'):
                        prefix = prefix[:-1]
                    prefix = '/'.join(
                        prefix.split('/')[:-1])
                    content = applyPrefix(content, prefix)
                data.write(
                    self.pack(content)
                )
                data.write(u"\n")
        return data.getvalue()


class JQueryUICustomJS(Resources):
    """This view aggregate javascripts according to the configuration. It has
    been created to not polute the portal_javascripts will all plugins"""
    _js = True
    _css = False
    _key = interfaces.IJQueryUIPlugins
    _mimetype = 'application/javascript'
    _toolid = 'portal_javascripts'
    _packer = JavascriptPacker

    def get_resources(self):
        """Return a list of resources (at least their ids) computed from
        the configuration provided by IJQueryUIPlugins's records in plone
        portal_registry"""
        settings = self.settings()
        deps = config.JQUERYUI_DEPENDENCIES
        alljs = deps.keys()
        resources = []
        wanted = []  # not ordered list of wanted plugins
        tpl = "++resource++jquery-ui/jquery.%s.min.js"
        ordered_plugins = copy(config.ORDERED_PLUGINS)
        for plugin in alljs:
            attr_name = plugin.replace('.', '_')
            is_wanted = getattr(settings, attr_name, False)
            if is_wanted:
                wanted.append(plugin)
                deps = config.JQUERYUI_DEPENDENCIES[plugin]
                for dep in deps:
                    wanted.append(dep)
        for plugin in alljs:
            if plugin not in wanted:
                ordered_plugins.remove(plugin)
        for plugin in ordered_plugins:
            resources.append(tpl % plugin)
            if plugin == 'ui.datepicker':
                resources.append('++resource++jquery-ui-i18n.js')
        return resources


class JQueryUICustomCSS(Resources):
    """ . """
    _key = interfaces.IJQueryUICSS
    _mimetype = 'text/css'
    _toolid = 'portal_css'
    _packer = CSSPacker
    _js = False
    _css = True


    def get_resources(self):
        """Return a list of resources (at least their ids) computed from
        the configuration provided by IJQueryUIPlugins's records in plone
        portal_registry"""
        settings = self.settings()
        resources_items = [
            ("css", config.CSS_RESOURCE_ID),
            ("patch", config.PATCH_RESOURCE_ID)]
        resources = []
        for skey, cssid in resources_items:
            if getattr(settings, skey, None):
                resources.append(cssid)
        return resources
