# encoding: utf-8
from __future__ import unicode_literals, print_function
import logging

from cssutils.css import CSSStyleSheet
from cssutils import CSSParser
import cssutils

from emails.compat import to_unicode


class PageStylesheets:

    """
    Store all html page styles and generates concatenated stylesheet
    """

    def __init__(self):
        self.urls = set()
        self._uri_properties = []
        self.sheets = []
        self.dirty = True
        self.element = None

    def update_tag(self):
        if self.element is not None:
            self._concatenate_sheets()
            cssText = self._cached_stylesheet.cssText
            cssText = cssText and to_unicode(cssText, 'utf-8') or ''
            self.element.text = cssText

    def attach_tag(self, element):
        self.element = element

    def append(self, url=None, text=None, absolute_url=None, local_loader=None):
        if (url is not None) and (url in self.urls):
            logging.debug('stylesheet url duplicate: %s', url)
            return
        self.sheets.append({'url': url, 'text': text, 'absolute_url': absolute_url or url,
                            'local_loader': local_loader})
        self.dirty = True

    def _concatenate_sheets(self):
        if self.dirty or (self._cached_stylesheet is None):
            r = CSSStyleSheet()
            uri_properties = []

            for d in self.sheets:
                local_loader = d.get('local_loader', None)
                text = d.get('text', None)
                uri = d.get('uri', None)
                absolute_url = d.get('absolute_url', None)

                if (text is None) and local_loader and uri:
                    text = local_loader[uri]

                if text:
                    sheet = CSSParser().parseString(text, href=absolute_url)
                else:
                    sheet = cssutils.parseUrl(href=absolute_url)

                for rule in sheet:
                    r.add(rule)
                    for p in _get_rule_uri_properties(rule):
                        uri_properties.append(p)

            self._uri_properties = uri_properties
            self._cached_stylesheet = r
            self.dirty = False

    @property
    def stylesheet(self):
        self._concatenate_sheets()
        return self._cached_stylesheet

    @property
    def uri_properties(self):
        self._concatenate_sheets()
        return self._uri_properties


class StyledTagWrapper:

    def __init__(self, el):
        self.el = el
        self.style = CSSParser().parseStyle(el.get('style'))

    def update(self):
        cssText = self.style.cssText
        if isinstance(cssText, str):
            cssText = to_unicode(cssText, 'utf-8')
        self.el.set('style', cssText)

    def uri_properties(self):
        for p in self.style.getProperties(all=True):
            for v in p.propertyValue:
                if v.type == 'URI':
                    yield v


# Stuff for extracting 'uri-properties' from CSS
# Inspired by cssutils examples

def _style_declarations(base):
    """recursive generator to find all CSSStyleDeclarations"""
    if hasattr(base, 'cssRules'):
        for rule in base.cssRules:
            for s in _style_declarations(rule):
                yield s
    elif hasattr(base, 'style'):
        yield base.style


def _get_rule_uri_properties(rule):
    for style in _style_declarations(rule):
        for p in style.getProperties(all=True):
            for v in p.propertyValue:
                if v.type == 'URI':
                    yield v


def get_stylesheets_uri_properties(sheet):
    for rule in sheet:
        for p in _get_rule_uri_properties(rule):
            yield p
