#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#
# Copyright 2004, 2005 Zuza Software Foundation
#
# This file is part of translate.
#
# translate is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# translate is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.

"""simpler wrapper to the elementtree XML parser"""

import sys
try:
    from xml.etree import ElementTree
except ImportError:
    from elementtree import ElementTree
    elementmod = 'elementtree'
else:
    elementmod = 'xml.etree'

# this is needed to prevent expat-version conflicts with wx >= 2.5.2.2
from xml.parsers import expat

# don't try this in Sphinx autodoc as xml.etree is Mock()ed
if sys.modules[elementmod].__path__ != '/dev/null':
    basicfixtag = ElementTree.fixtag


def makefixtagproc(namespacemap):
    """Constructs an alternative fixtag procedure that will use appropriate
    names for namespaces."""

    def fixtag(tag, namespaces):
        """Given a decorated tag (of the form {uri}tag), return prefixed
        tag and namespace declaration, if any."""
        if isinstance(tag, ElementTree.QName):
            tag = tag.text
        namespace_uri, tag = tag[1:].split("}", 1)
        prefix = namespaces.get(namespace_uri)
        if prefix is None:
            if namespace_uri in namespacemap:
                prefix = namespacemap[namespace_uri]
            else:
                prefix = "ns%d" % len(namespaces)
            namespaces[namespace_uri] = prefix
            xmlns = ("xmlns:%s" % prefix, namespace_uri)
        else:
            xmlns = None
        return "%s:%s" % (prefix, tag), xmlns
    return fixtag


def splitnamespace(fulltag):
    if '{' in fulltag:
        namespace = fulltag[fulltag.find('{'):fulltag.find('}')+1]
    else:
        namespace = ""
    tag = fulltag.replace(namespace, "", 1)
    return namespace, tag


class XMLWrapper:
    """simple wrapper for xml objects"""

    def __init__(self, obj):
        """construct object from the elementtree item"""
        self.obj = obj
        self.namespace, self.tag = splitnamespace(self.obj.tag)
        self.attrib = {}
        for fullkey, value in self.obj.attrib.iteritems():
            namespace, key = splitnamespace(fullkey)
            self.attrib[key] = value

    def getchild(self, searchtag, tagclass=None):
        """get a child with the given tag name"""
        if tagclass is None:
            tagclass = XMLWrapper
        for childobj in self.obj.getiterator():
            # getiterator() includes self...
            if childobj == self.obj:
                continue
            childns, childtag = splitnamespace(childobj.tag)
            if childtag == searchtag:
                child = tagclass(childobj)
                return child
        raise KeyError("could not find child with tag %r" % searchtag)

    def getchildren(self, searchtag, tagclass=None, excludetags=[]):
        """get all children with the given tag name"""
        if tagclass is None:
            tagclass = XMLWrapper
        childobjects = []
        for childobj in self.obj.getiterator():
            # getiterator() includes self...
            if childobj == self.obj:
                continue
            childns, childtag = splitnamespace(childobj.tag)
            if childtag == searchtag:
                childobjects.append(childobj)
        children = [tagclass(childobj) for childobj in childobjects]
        return children

    def gettext(self, searchtag):
        """get some contained text"""
        return self.getchild(searchtag).obj.text

    def getxml(self, encoding=None):
        return ElementTree.tostring(self.obj, encoding)

    def getplaintext(self, excludetags=[]):
        text = ""
        if self.obj.text != None:
            text += self.obj.text
        for child in self.obj._children:
            simplechild = XMLWrapper(child)
            if simplechild.tag not in excludetags:
                text += simplechild.getplaintext(excludetags)
        if self.obj.tail != None:
            text += self.obj.tail
        return text

    def getvalues(self, searchtag):
        """get some contained values..."""
        values = [child.obj.text for child in self.getchildren(searchtag)]
        return values

    def __repr__(self):
        """return a representation of the object"""
        return self.tag + ':' + repr(self.__dict__)

    def getattr(self, attrname):
        """gets an attribute of the tag"""
        return self.attrib[attrname]

    def write(self, file, encoding="UTF-8"):
        """writes the object as XML to a file..."""
        e = ElementTree.ElementTree(self.obj)
        e.write(file, encoding)


def BuildTree(xmlstring):
    parser = ElementTree.XMLTreeBuilder()
    parser.feed(xmlstring)
    return parser.close()


def MakeElement(tag, attrib={}, **extraargs):
    return ElementTree.Element(tag, attrib, **extraargs)
