#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.


from grit.format.policy_templates.writers import template_writer


class XMLFormattedWriter(template_writer.TemplateWriter):
  '''Helper class for generating XML-based templates.
  '''

  def AddElement(self, parent, name, attrs=None, text=None):
    '''
    Adds a new XML Element as a child to an existing element or the Document.

    Args:
      parent: An XML element or the document, where the new element will be
        added.
      name: The name of the new element.
      attrs: A dictionary of the attributes' names and values for the new
        element.
      text: Text content for the new element.

    Returns:
      The created new element.
    '''
    if attrs == None:
      attrs = {}

    doc = parent.ownerDocument
    element = doc.createElement(name)
    for key, value in attrs.iteritems():
      element.setAttribute(key, value)
    if text:
      element.appendChild(doc.createTextNode(text))
    parent.appendChild(element)
    return element

  def AddText(self, parent, text):
    '''Adds text to a parent node.
    '''
    doc = parent.ownerDocument
    parent.appendChild(doc.createTextNode(text))

  def AddAttribute(self, parent, name, value):
    '''Adds a new attribute to the parent Element. If an attribute with the
    given name already exists then it will be replaced.
    '''
    doc = parent.ownerDocument
    attribute = doc.createAttribute(name)
    attribute.value = value
    parent.setAttributeNode(attribute)

  def ToPrettyXml(self, doc):
    # return doc.toprettyxml(indent='  ')
    # The above pretty-printer does not print the doctype and adds spaces
    # around texts, e.g.:
    #  <string>
    #    value of the string
    #  </string>
    # This is problematic both for the OSX Workgroup Manager (plist files) and
    # the Windows Group Policy Editor (admx files). What they need instead:
    #  <string>value of string</string>
    # So we use the poor man's pretty printer here. It assumes that there are
    # no mixed-content nodes.
    # Get all the XML content in a one-line string.
    xml = doc.toxml()
    # Determine where the line breaks will be. (They will only be between tags.)
    lines = xml[1:len(xml) - 1].split('><')
    indent = ''
    res = ''
    # Determine indent for each line.
    for i, line in enumerate(lines):
      if line[0] == '/':
        # If the current line starts with a closing tag, decrease indent before
        # printing.
        indent = indent[2:]
      lines[i] = indent + '<' + line + '>'
      if (line[0] not in ['/', '?', '!'] and '</' not in line and
          line[len(line) - 1] != '/'):
        # If the current line starts with an opening tag and does not conatin a
        # closing tag, increase indent after the line is printed.
        indent += '  '
    # Reconstruct XML text from the lines.
    return '\n'.join(lines)
