#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""\
Usage: %prog RULES

RULES is a file defining a set of diazo rules in css syntax, e.g:

<rules xmlns="http://namespaces.plone.org/diazo"
       xmlns:css="http://namespaces.plone.org/diazo/css">
       <copy css:content="#content-wrapper" css:theme="#page-content"/>
</rules>\
"""

from __future__ import absolute_import

from cssselect import GenericTranslator
from diazo import utils
from lxml import etree
from optparse import OptionParser

import logging
import sys


logger = logging.getLogger('diazo')
usage = __doc__


class LocationPathTranslator(GenericTranslator):
    def xpath_descendant_combinator(self, left, right):
        """right is a child, grand-child or further descendant of left"""
        return left.join('//', right)


_generic_translator = GenericTranslator()
_location_path_translator = LocationPathTranslator()


def convert_css_selectors(rules):
    """Convert css rules to xpath rules element tree in place
    """
    # XXX: There is a :root pseudo-class  # NOQA: T000
    # http://www.w3.org/TR/css3-selectors/#root-pseudo
    # We may wish to add support to lxml.cssselect for it some day.
    for element in rules.xpath(
        "//@*[namespace-uri()='{nsp}']/..".format(nsp=utils.namespaces['css']),
    ):
        tag_namespace = utils.namespace(element.tag)
        css_prefix = element.attrib.get(
            utils.fullname(
                utils.namespaces['css'],
                'prefix',
            ),
            None,
        )
        for name, value in element.attrib.items():
            if not name.startswith(
                '{%s}' % utils.namespaces['css'],  # NOQA: S001
            ):
                continue
            localname = utils.localname(name)
            if localname == 'prefix':
                continue
            if not value:
                element.attrib[localname] = ''
                continue
            if (
                tag_namespace == utils.namespaces['diazo'] and
                localname in
                (
                    'content',
                    'content-children',
                    'if-content',
                    'if-not-content',
                ) or (
                    tag_namespace == utils.namespaces['xsl'] and
                    localname in ('match',)
                )
            ):
                prefix = css_prefix or '//'
                tr = _location_path_translator
            else:
                prefix = css_prefix or 'descendant-or-self::'
                tr = _generic_translator
            element.attrib[localname] = tr.css_to_xpath(value, prefix=prefix)

    return rules


def main():
    """Called from console script
    """
    parser = OptionParser(usage=usage)
    parser.add_option(
        '-o',
        '--output',
        metavar='output.html',
        help='Output filename (instead of stdout)',
        dest='output',
        default=sys.stdout,
    )
    parser.add_option(
        '-p',
        '--pretty-print',
        action='store_true',
        help='Pretty print output',
        dest='pretty_print',
        default=False,
    )
    (options, args) = parser.parse_args()

    if len(args) != 1:
        parser.error('Invalid number of arguments')
    rules = etree.parse(args[0])
    convert_css_selectors(rules)
    rules.write(options.output, pretty_print=options.pretty_print)


if __name__ == '__main__':
    main()
