#!/usr/bin/env python
#
# Copyright 2013 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.

"""Convert Android xml resources to API 14 compatible.

There are two reasons that we cannot just use API 17 attributes,
so we are generating another set of resources by this script.

1. paddingStart attribute can cause a crash on Galaxy Tab 2.
2. There is a bug that paddingStart does not override paddingLeft on
   JB-MR1. This is fixed on JB-MR2.

Therefore, this resource generation script can be removed when
we drop the support for JB-MR1.

Please refer to http://crbug.com/235118 for the details.
"""

import optparse
import os
import re
import shutil
import sys
import xml.dom.minidom as minidom

from util import build_utils

# Note that we are assuming 'android:' is an alias of
# the namespace 'http://schemas.android.com/apk/res/android'.

GRAVITY_ATTRIBUTES = ('android:gravity', 'android:layout_gravity')

# Almost all the attributes that has "Start" or "End" in
# its name should be mapped.
ATTRIBUTES_TO_MAP = {'paddingStart' : 'paddingLeft',
                     'drawableStart' : 'drawableLeft',
                     'layout_alignStart' : 'layout_alignLeft',
                     'layout_marginStart' : 'layout_marginLeft',
                     'layout_alignParentStart' : 'layout_alignParentLeft',
                     'layout_toStartOf' : 'layout_toLeftOf',
                     'paddingEnd' : 'paddingRight',
                     'drawableEnd' : 'drawableRight',
                     'layout_alignEnd' : 'layout_alignRight',
                     'layout_marginEnd' : 'layout_marginRight',
                     'layout_alignParentEnd' : 'layout_alignParentRight',
                     'layout_toEndOf' : 'layout_toRightOf'}

ATTRIBUTES_TO_MAP = dict(['android:' + k, 'android:' + v] for k, v
                         in ATTRIBUTES_TO_MAP.iteritems())

ATTRIBUTES_TO_MAP_REVERSED = dict([v, k] for k, v
                                  in ATTRIBUTES_TO_MAP.iteritems())


def IterateXmlElements(node):
  """minidom helper function that iterates all the element nodes.
  Iteration order is pre-order depth-first."""
  if node.nodeType == node.ELEMENT_NODE:
    yield node
  for child_node in node.childNodes:
    for child_node_element in IterateXmlElements(child_node):
      yield child_node_element


def ParseAndReportErrors(filename):
  try:
    return minidom.parse(filename)
  except Exception:
    import traceback
    traceback.print_exc()
    sys.stderr.write('Failed to parse XML file: %s\n' % filename)
    sys.exit(1)


def AssertNotDeprecatedAttribute(name, value, filename):
  """Raises an exception if the given attribute is deprecated."""
  msg = None
  if name in ATTRIBUTES_TO_MAP_REVERSED:
    msg = '{0} should use {1} instead of {2}'.format(filename,
        ATTRIBUTES_TO_MAP_REVERSED[name], name)
  elif name in GRAVITY_ATTRIBUTES and ('left' in value or 'right' in value):
    msg = '{0} should use start/end instead of left/right for {1}'.format(
        filename, name)

  if msg:
    msg += ('\nFor background, see: http://android-developers.blogspot.com/'
            '2013/03/native-rtl-support-in-android-42.html\n'
            'If you have a legitimate need for this attribute, discuss with '
            'kkimlabs@chromium.org or newt@chromium.org')
    raise Exception(msg)


def WriteDomToFile(dom, filename):
  """Write the given dom to filename."""
  build_utils.MakeDirectory(os.path.dirname(filename))
  with open(filename, 'w') as f:
    dom.writexml(f, '', '  ', '\n', encoding='utf-8')


def HasStyleResource(dom):
  """Return True if the dom is a style resource, False otherwise."""
  root_node = IterateXmlElements(dom).next()
  return bool(root_node.nodeName == 'resources' and
              list(root_node.getElementsByTagName('style')))


def ErrorIfStyleResourceExistsInDir(input_dir):
  """If a style resource is in input_dir, raises an exception."""
  for input_filename in build_utils.FindInDirectory(input_dir, '*.xml'):
    dom = ParseAndReportErrors(input_filename)
    if HasStyleResource(dom):
      raise Exception('error: style file ' + input_filename +
                      ' should be under ' + input_dir +
                      '-v17 directory. Please refer to '
                      'http://crbug.com/243952 for the details.')


def GenerateV14LayoutResourceDom(dom, filename, assert_not_deprecated=True):
  """Convert layout resource to API 14 compatible layout resource.

  Args:
    dom: Parsed minidom object to be modified.
    filename: Filename that the DOM was parsed from.
    assert_not_deprecated: Whether deprecated attributes (e.g. paddingLeft) will
                           cause an exception to be thrown.

  Returns:
    True if dom is modified, False otherwise.
  """
  is_modified = False

  # Iterate all the elements' attributes to find attributes to convert.
  for element in IterateXmlElements(dom):
    for name, value in list(element.attributes.items()):
      # Convert any API 17 Start/End attributes to Left/Right attributes.
      # For example, from paddingStart="10dp" to paddingLeft="10dp"
      # Note: gravity attributes are not necessary to convert because
      # start/end values are backward-compatible. Explained at
      # https://plus.sandbox.google.com/+RomanNurik/posts/huuJd8iVVXY?e=Showroom
      if name in ATTRIBUTES_TO_MAP:
        element.setAttribute(ATTRIBUTES_TO_MAP[name], value)
        del element.attributes[name]
        is_modified = True
      elif assert_not_deprecated:
        AssertNotDeprecatedAttribute(name, value, filename)

  return is_modified


def GenerateV14StyleResourceDom(dom, filename, assert_not_deprecated=True):
  """Convert style resource to API 14 compatible style resource.

  Args:
    dom: Parsed minidom object to be modified.
    filename: Filename that the DOM was parsed from.
    assert_not_deprecated: Whether deprecated attributes (e.g. paddingLeft) will
                           cause an exception to be thrown.

  Returns:
    True if dom is modified, False otherwise.
  """
  is_modified = False

  for style_element in dom.getElementsByTagName('style'):
    for item_element in style_element.getElementsByTagName('item'):
      name = item_element.attributes['name'].value
      value = item_element.childNodes[0].nodeValue
      if name in ATTRIBUTES_TO_MAP:
        item_element.attributes['name'].value = ATTRIBUTES_TO_MAP[name]
        is_modified = True
      elif assert_not_deprecated:
        AssertNotDeprecatedAttribute(name, value, filename)

  return is_modified


def GenerateV14LayoutResource(input_filename, output_v14_filename,
                              output_v17_filename):
  """Convert API 17 layout resource to API 14 compatible layout resource.

  It's mostly a simple replacement, s/Start/Left s/End/Right,
  on the attribute names.
  If the generated resource is identical to the original resource,
  don't do anything. If not, write the generated resource to
  output_v14_filename, and copy the original resource to output_v17_filename.
  """
  dom = ParseAndReportErrors(input_filename)
  is_modified = GenerateV14LayoutResourceDom(dom, input_filename)

  if is_modified:
    # Write the generated resource.
    WriteDomToFile(dom, output_v14_filename)

    # Copy the original resource.
    build_utils.MakeDirectory(os.path.dirname(output_v17_filename))
    shutil.copy2(input_filename, output_v17_filename)


def GenerateV14StyleResource(input_filename, output_v14_filename):
  """Convert API 17 style resources to API 14 compatible style resource.

  Write the generated style resource to output_v14_filename.
  It's mostly a simple replacement, s/Start/Left s/End/Right,
  on the attribute names.
  """
  dom = ParseAndReportErrors(input_filename)
  GenerateV14StyleResourceDom(dom, input_filename)

  # Write the generated resource.
  WriteDomToFile(dom, output_v14_filename)


def GenerateV14LayoutResourcesInDir(input_dir, output_v14_dir, output_v17_dir):
  """Convert layout resources to API 14 compatible resources in input_dir."""
  for input_filename in build_utils.FindInDirectory(input_dir, '*.xml'):
    rel_filename = os.path.relpath(input_filename, input_dir)
    output_v14_filename = os.path.join(output_v14_dir, rel_filename)
    output_v17_filename = os.path.join(output_v17_dir, rel_filename)
    GenerateV14LayoutResource(input_filename, output_v14_filename,
                              output_v17_filename)


def GenerateV14StyleResourcesInDir(input_dir, output_v14_dir):
  """Convert style resources to API 14 compatible resources in input_dir."""
  for input_filename in build_utils.FindInDirectory(input_dir, '*.xml'):
    rel_filename = os.path.relpath(input_filename, input_dir)
    output_v14_filename = os.path.join(output_v14_dir, rel_filename)
    GenerateV14StyleResource(input_filename, output_v14_filename)


def VerifyV14ResourcesInDir(input_dir, resource_type):
  """Verify that the resources in input_dir is compatible with v14, i.e., they
  don't use attributes that cause crashes on certain devices. Print an error if
  they have."""
  for input_filename in build_utils.FindInDirectory(input_dir, '*.xml'):
    exception_message = ('error : ' + input_filename + ' has an RTL attribute, '
                        'i.e., attribute that has "start" or "end" in its name.'
                        ' Pre-v17 resources should not include it because it '
                        'can cause crashes on certain devices. Please refer to '
                        'http://crbug.com/243952 for the details.')
    dom = ParseAndReportErrors(input_filename)
    if resource_type in ('layout', 'xml'):
      if GenerateV14LayoutResourceDom(dom, input_filename, False):
        raise Exception(exception_message)
    elif resource_type == 'values':
      if GenerateV14StyleResourceDom(dom, input_filename, False):
        raise Exception(exception_message)


def AssertNoDeprecatedAttributesInDir(input_dir, resource_type):
  """Raises an exception if resources in input_dir have deprecated attributes,
  e.g., paddingLeft, paddingRight"""
  for input_filename in build_utils.FindInDirectory(input_dir, '*.xml'):
    dom = ParseAndReportErrors(input_filename)
    if resource_type in ('layout', 'xml'):
      GenerateV14LayoutResourceDom(dom, input_filename)
    elif resource_type == 'values':
      GenerateV14StyleResourceDom(dom, input_filename)


def ParseArgs():
  """Parses command line options.

  Returns:
    An options object as from optparse.OptionsParser.parse_args()
  """
  parser = optparse.OptionParser()
  parser.add_option('--res-dir',
                    help='directory containing resources '
                         'used to generate v14 compatible resources')
  parser.add_option('--res-v14-compatibility-dir',
                    help='output directory into which '
                         'v14 compatible resources will be generated')
  parser.add_option('--stamp', help='File to touch on success')
  parser.add_option('--verify-only', action="store_true", help='Do not generate'
      ' v14 resources. Instead, just verify that the resources are already '
      "compatible with v14, i.e. they don't use attributes that cause crashes "
      'on certain devices.')

  options, args = parser.parse_args()

  if args:
    parser.error('No positional arguments should be given.')

  # Check that required options have been provided.
  required_options = ('res_dir', 'res_v14_compatibility_dir')
  build_utils.CheckOptions(options, parser, required=required_options)
  return options

def GenerateV14Resources(res_dir, res_v14_dir, verify_only):
  for name in os.listdir(res_dir):
    if not os.path.isdir(os.path.join(res_dir, name)):
      continue

    dir_pieces = name.split('-')
    resource_type = dir_pieces[0]
    qualifiers = dir_pieces[1:]

    api_level_qualifier_index = -1
    api_level_qualifier = ''
    for index, qualifier in enumerate(qualifiers):
      if re.match('v[0-9]+$', qualifier):
        api_level_qualifier_index = index
        api_level_qualifier = qualifier
        break

    # Android pre-v17 API doesn't support RTL. Skip.
    if 'ldrtl' in qualifiers:
      continue

    input_dir = os.path.abspath(os.path.join(res_dir, name))

    if verify_only:
      if not api_level_qualifier or int(api_level_qualifier[1:]) < 17:
        VerifyV14ResourcesInDir(input_dir, resource_type)
      else:
        AssertNoDeprecatedAttributesInDir(input_dir, resource_type)
    else:
      # We also need to copy the original v17 resource to *-v17 directory
      # because the generated v14 resource will hide the original resource.
      output_v14_dir = os.path.join(res_v14_dir, name)
      output_v17_dir = os.path.join(res_v14_dir, name + '-v17')

      # We only convert layout resources under layout*/, xml*/,
      # and style resources under values*/.
      if resource_type in ('layout', 'xml'):
        if not api_level_qualifier:
          GenerateV14LayoutResourcesInDir(input_dir, output_v14_dir,
                                          output_v17_dir)
      elif resource_type == 'values':
        if api_level_qualifier == 'v17':
          output_qualifiers = qualifiers[:]
          del output_qualifiers[api_level_qualifier_index]
          output_v14_dir = os.path.join(res_v14_dir,
                                        '-'.join([resource_type] +
                                                 output_qualifiers))
          GenerateV14StyleResourcesInDir(input_dir, output_v14_dir)
        elif not api_level_qualifier:
          ErrorIfStyleResourceExistsInDir(input_dir)

def main():
  options = ParseArgs()

  res_v14_dir = options.res_v14_compatibility_dir

  build_utils.DeleteDirectory(res_v14_dir)
  build_utils.MakeDirectory(res_v14_dir)

  GenerateV14Resources(options.res_dir, res_v14_dir, options.verify_only)

  if options.stamp:
    build_utils.Touch(options.stamp)

if __name__ == '__main__':
  sys.exit(main())

