# Copyright 2019 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.

"""
Merges multiple Apple Property List files (.plist) and perform variables
substitutions $(VARIABLE) in the Property List string values.
"""

import argparse
import json
import re
import subprocess
import sys


# Pattern representing a variable to substitue in a string value.
VARIABLE_PATTERN = re.compile(r'\$\(([^)]*)\)')


def LoadPlist(plist_path):
  """Loads Apple Property List file at |plist_path|."""
  return json.loads(
      subprocess.check_output(
          ['plutil', '-convert', 'json', '-o', '-', plist_path]))


def SavePlist(plist_path, content, format):
  """Saves |content| as Apple Property List in |format| at |plist_path|."""
  proc = subprocess.Popen(
      ['plutil', '-convert', format, '-o', plist_path, '-'],
      stdin=subprocess.PIPE)
  output, _ = proc.communicate(json.dumps(content))
  if proc.returncode:
    raise subprocess.CalledProcessError(
        proc.returncode,
        ['plutil', '-convert', format, '-o', plist_path, '-'],
        output)


def MergeObjects(obj1, obj2):
  """Merges two objects (either dictionary, list, string or numbers)."""
  if type(obj1) != type(obj2):
    return obj2

  if isinstance(obj2, dict):
    result = dict(obj1)
    for key in obj2:
      value1 = obj1.get(key, None)
      value2 = obj2.get(key, None)
      result[key] = MergeObjects(value1, value2)
    return result

  if isinstance(obj2, list):
    return obj1 + obj2

  return obj2


def MergePlists(plist_paths):
  """Loads and merges all Apple Property List files at |plist_paths|."""
  plist = {}
  for plist_path in plist_paths:
    plist = MergeObjects(plist, LoadPlist(plist_path))
  return plist


def PerformSubstitutions(plist, substitutions):
  """Performs variables substitutions in |plist| given by |substitutions|."""
  if isinstance(plist, dict):
    result = dict(plist)
    for key in plist:
      result[key] = PerformSubstitutions(plist[key], substitutions)
    return result

  if isinstance(plist, list):
    return [ PerformSubstitutions(item, substitutions) for item in plist ]

  if isinstance(plist, (str, unicode)):
    result = plist
    while True:
      match = VARIABLE_PATTERN.search(result)
      if not match:
        break

      extent = match.span()
      expand = substitutions[match.group(1)]
      result = result[:extent[0]] + expand + result[extent[1]:]
    return result

  return plist


def PerformSubstitutionsFrom(plist, substitutions_path):
  """Performs variable substitutions in |plist| from |substitutions_path|."""
  with open(substitutions_path) as substitutions_file:
    return PerformSubstitutions(plist, json.load(substitutions_file))


def ParseArgs(argv):
  """Parses command line arguments."""
  parser = argparse.ArgumentParser(
      description=__doc__,
      formatter_class=argparse.ArgumentDefaultsHelpFormatter)

  parser.add_argument(
      '-s', '--substitutions',
      help='path to a JSON file containing variable substitutions')
  parser.add_argument(
      '-f', '--format', default='json', choices=('json', 'binary1', 'xml1'),
      help='format of the generated file')
  parser.add_argument(
      '-o', '--output', default='-',
      help='path to the result; - means stdout')
  parser.add_argument(
      'inputs', nargs='+',
      help='path of the input files to merge')

  return parser.parse_args(argv)


def main(argv):
  args = ParseArgs(argv)

  data = MergePlists(args.inputs)
  if args.substitutions:
    data = PerformSubstitutionsFrom(
        data, args.substitutions)

  SavePlist(args.output, data, args.format)


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
