# Copyright 2019 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Contains common helpers for working with Android manifests."""

import hashlib
import os
import re
import shlex
import sys
import xml.dom.minidom as minidom
from xml.etree import ElementTree

from util import build_utils
import action_helpers  # build_utils adds //build to sys.path.

ANDROID_NAMESPACE = 'http://schemas.android.com/apk/res/android'
TOOLS_NAMESPACE = 'http://schemas.android.com/tools'
DIST_NAMESPACE = 'http://schemas.android.com/apk/distribution'
EMPTY_ANDROID_MANIFEST_PATH = os.path.abspath(
    os.path.join(os.path.dirname(__file__), '..', '..', 'AndroidManifest.xml'))
# When normalizing for expectation matching, wrap these tags when they are long
# or else they become very hard to read.
_WRAP_CANDIDATES = (
    '<manifest',
    '<application',
    '<activity',
    '<provider',
    '<receiver',
    '<service',
)
# Don't wrap lines shorter than this.
_WRAP_LINE_LENGTH = 100

_xml_namespace_initialized = False


def _RegisterElementTreeNamespaces():
  global _xml_namespace_initialized
  if _xml_namespace_initialized:
    return
  _xml_namespace_initialized = True
  ElementTree.register_namespace('android', ANDROID_NAMESPACE)
  ElementTree.register_namespace('tools', TOOLS_NAMESPACE)
  ElementTree.register_namespace('dist', DIST_NAMESPACE)


def NamespacedGet(node, key):
  return node.get('{%s}%s' % (ANDROID_NAMESPACE, key))


def NamespacedSet(node, key, value):
  node.set('{%s}%s' % (ANDROID_NAMESPACE, key), value)


def ParseManifest(path):
  """Parses an AndroidManifest.xml using ElementTree.

  Registers required namespaces, creates application node if missing, adds any
  missing namespaces for 'android', 'tools' and 'dist'.

  Returns tuple of:
    doc: Root xml document.
    manifest_node: the <manifest> node.
    app_node: the <application> node.
  """
  _RegisterElementTreeNamespaces()
  doc = ElementTree.parse(path)
  # ElementTree.find does not work if the required tag is the root.
  if doc.getroot().tag == 'manifest':
    manifest_node = doc.getroot()
  else:
    manifest_node = doc.find('manifest')
  assert manifest_node is not None, 'Manifest is none for path ' + path

  app_node = doc.find('application')
  if app_node is None:
    app_node = ElementTree.SubElement(manifest_node, 'application')

  return doc, manifest_node, app_node


def SaveManifest(doc, path):
  with action_helpers.atomic_output(path) as f:
    f.write(ElementTree.tostring(doc.getroot(), encoding='UTF-8'))


def GetPackage(manifest_node):
  return manifest_node.get('package')


def SetUsesSdk(manifest_node,
               target_sdk_version,
               min_sdk_version,
               max_sdk_version=None):
  uses_sdk_node = manifest_node.find('./uses-sdk')
  if uses_sdk_node is None:
    uses_sdk_node = ElementTree.SubElement(manifest_node, 'uses-sdk')
  NamespacedSet(uses_sdk_node, 'targetSdkVersion', target_sdk_version)
  NamespacedSet(uses_sdk_node, 'minSdkVersion', min_sdk_version)
  if max_sdk_version:
    NamespacedSet(uses_sdk_node, 'maxSdkVersion', max_sdk_version)


def SetTargetApiIfUnset(manifest_node, target_sdk_version):
  uses_sdk_node = manifest_node.find('./uses-sdk')
  if uses_sdk_node is None:
    uses_sdk_node = ElementTree.SubElement(manifest_node, 'uses-sdk')
  curr_target_sdk_version = NamespacedGet(uses_sdk_node, 'targetSdkVersion')
  if curr_target_sdk_version is None:
    NamespacedSet(uses_sdk_node, 'targetSdkVersion', target_sdk_version)
  return curr_target_sdk_version is None


def _SortAndStripElementTree(root):
  # Sort alphabetically with two exceptions:
  # 1) Put <application> node last (since it's giant).
  # 2) Put android:name before other attributes.
  def element_sort_key(node):
    if node.tag == 'application':
      return 'z'
    ret = ElementTree.tostring(node)
    # ElementTree.tostring inserts namespace attributes for any that are needed
    # for the node or any of its descendants. Remove them so as to prevent a
    # change to a child that adds/removes a namespace usage from changing sort
    # order.
    return re.sub(r' xmlns:.*?".*?"', '', ret.decode('utf8'))

  name_attr = '{%s}name' % ANDROID_NAMESPACE

  def attribute_sort_key(tup):
    return ('', '') if tup[0] == name_attr else tup

  def helper(node):
    for child in node:
      if child.text and child.text.isspace():
        child.text = None
      helper(child)

    # Sort attributes (requires Python 3.8+).
    node.attrib = dict(sorted(node.attrib.items(), key=attribute_sort_key))

    # Sort nodes
    node[:] = sorted(node, key=element_sort_key)

  helper(root)


def _SplitElement(line):
  """Parses a one-line xml node into ('<tag', ['a="b"', ...]], '/>')."""

  # Shlex splits nicely, but removes quotes. Need to put them back.
  def restore_quotes(value):
    return value.replace('=', '="', 1) + '"'

  # Simplify restore_quotes by separating />.
  assert line.endswith('>'), line
  end_tag = '>'
  if line.endswith('/>'):
    end_tag = '/>'
  line = line[:-len(end_tag)]

  # Use shlex to avoid having to re-encode &quot;, etc.
  parts = shlex.split(line)
  start_tag = parts[0]
  attrs = parts[1:]

  return start_tag, [restore_quotes(x) for x in attrs], end_tag


def _CreateNodeHash(lines):
  """Computes a hash (md5) for the first XML node found in |lines|.

  Args:
    lines: List of strings containing pretty-printed XML.

  Returns:
    Positive 32-bit integer hash of the node (including children).
  """
  target_indent = lines[0].find('<')
  tag_closed = False
  for i, l in enumerate(lines[1:]):
    cur_indent = l.find('<')
    if cur_indent != -1 and cur_indent <= target_indent:
      tag_lines = lines[:i + 1]
      break
    if not tag_closed and 'android:name="' in l:
      # To reduce noise of node tags changing, use android:name as the
      # basis the hash since they usually unique.
      tag_lines = [l]
      break
    tag_closed = tag_closed or '>' in l
  else:
    assert False, 'Did not find end of node:\n' + '\n'.join(lines)

  # Insecure and truncated hash as it only needs to be unique vs. its neighbors.
  return hashlib.md5(('\n'.join(tag_lines)).encode('utf8')).hexdigest()[:8]


def _IsSelfClosing(lines):
  """Given pretty-printed xml, returns whether first node is self-closing."""
  for l in lines:
    idx = l.find('>')
    if idx != -1:
      return l[idx - 1] == '/'
  raise RuntimeError('Did not find end of tag:\n%s' % '\n'.join(lines))


def _AddDiffTags(lines):
  # When multiple identical tags appear sequentially, XML diffs can look like:
  # +  </tag>
  # +  <tag>
  # rather than:
  # +  <tag>
  # +  </tag>
  # To reduce confusion, add hashes to tags.
  # This also ensures changed tags show up with outer <tag> elements rather than
  # showing only changed attributes.
  hash_stack = []
  for i, l in enumerate(lines):
    stripped = l.lstrip()
    # Ignore non-indented tags and lines that are not the start/end of a node.
    if l[0] != ' ' or stripped[0] != '<':
      continue
    # Ignore self-closing nodes that fit on one line.
    if l[-2:] == '/>':
      continue
    # Ignore <application> since diff tag changes with basically any change.
    if stripped.lstrip('</').startswith('application'):
      continue

    # Check for the closing tag (</foo>).
    if stripped[1] != '/':
      cur_hash = _CreateNodeHash(lines[i:])
      if not _IsSelfClosing(lines[i:]):
        hash_stack.append(cur_hash)
    else:
      cur_hash = hash_stack.pop()
    lines[i] += '  # DIFF-ANCHOR: {}'.format(cur_hash)
  assert not hash_stack, 'hash_stack was not empty:\n' + '\n'.join(hash_stack)


def NormalizeManifest(manifest_contents, version_code_offset,
                      library_version_offset):
  _RegisterElementTreeNamespaces()
  # This also strips comments and sorts node attributes alphabetically.
  root = ElementTree.fromstring(manifest_contents)
  package = GetPackage(root)

  app_node = root.find('application')
  if app_node is not None:
    # android:debuggable is added when !is_official_build. Strip it out to avoid
    # expectation diffs caused by not adding is_official_build. Play store
    # blocks uploading apps with it set, so there's no risk of it slipping in.
    debuggable_name = '{%s}debuggable' % ANDROID_NAMESPACE
    if debuggable_name in app_node.attrib:
      del app_node.attrib[debuggable_name]

    version_code = NamespacedGet(root, 'versionCode')
    if version_code and version_code_offset:
      version_code = int(version_code) - int(version_code_offset)
      NamespacedSet(root, 'versionCode', f'OFFSET={version_code}')
    version_name = NamespacedGet(root, 'versionName')
    if version_name:
      version_name = re.sub(r'\d+', '#', version_name)
      NamespacedSet(root, 'versionName', version_name)

    # Trichrome's static library version number is updated daily. To avoid
    # frequent manifest check failures, we remove the exact version number
    # during normalization.
    for node in app_node:
      if node.tag in ['uses-static-library', 'static-library']:
        version = NamespacedGet(node, 'version')
        if version and library_version_offset:
          version = int(version) - int(library_version_offset)
          NamespacedSet(node, 'version', f'OFFSET={version}')

  # We also remove the exact package name (except the one at the root level)
  # to avoid noise during manifest comparison.
  def blur_package_name(node):
    for key in node.keys():
      node.set(key, node.get(key).replace(package, '$PACKAGE'))

    for child in node:
      blur_package_name(child)

  # We only blur the package names of non-root nodes because they generate a lot
  # of diffs when doing manifest checks for upstream targets. We still want to
  # have 1 piece of package name not blurred just in case the package name is
  # mistakenly changed.
  for child in root:
    blur_package_name(child)

  _SortAndStripElementTree(root)

  # Fix up whitespace/indentation.
  dom = minidom.parseString(ElementTree.tostring(root))
  out_lines = []
  for l in dom.toprettyxml(indent='  ').splitlines():
    if not l or l.isspace():
      continue
    if len(l) > _WRAP_LINE_LENGTH and any(x in l for x in _WRAP_CANDIDATES):
      indent = ' ' * l.find('<')
      start_tag, attrs, end_tag = _SplitElement(l)
      out_lines.append('{}{}'.format(indent, start_tag))
      for attribute in attrs:
        out_lines.append('{}    {}'.format(indent, attribute))
      out_lines[-1] += '>'
      # Heuristic: Do not allow multi-line tags to be self-closing since these
      # can generally be allowed to have nested elements. When diffing, it adds
      # noise if the base file is self-closing and the non-base file is not
      # self-closing.
      if end_tag == '/>':
        out_lines.append('{}{}>'.format(indent, start_tag.replace('<', '</')))
    else:
      out_lines.append(l)

  # Make output more diff-friendly.
  _AddDiffTags(out_lines)

  return '\n'.join(out_lines) + '\n'
