# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Script for dumping and/or comparing build config contents."""

from __future__ import print_function

import json
import pprint

from chromite.cbuildbot import cbuildbot_config
from chromite.lib import commandline
from chromite.lib import cros_build_lib


class _JSONEncoder(json.JSONEncoder):
  """Json Encoder that encodes objects as their dictionaries."""
  # pylint: disable=E0202
  def default(self, obj):
    return self.encode(obj.__dict__)


def _InjectDisplayPosition(config):
  """Add field to help buildbot masters order builders on the waterfall.

  Args:
    config: A dict of build config items.

  Returns:
    A similar config where each config item has a new 'display_position' value.
  """
  def _GetSortKey(items):
    my_config = items[1]
    # Allow configs to override the display_position.
    return (my_config.get('display_position', 1000000),
            cbuildbot_config.GetDisplayPosition(my_config['name']),
            my_config['internal'], my_config['vm_tests'])

  source = sorted(config.iteritems(), key=_GetSortKey)
  return dict((name, dict(value.items() + [('display_position', idx)]))
              for idx, (name, value) in enumerate(source))


def _DumpConfigJson(cfg):
  """Dump |cfg| contents in JSON format.

  Args:
    cfg: A single build config.
  """
  print(json.dumps(cfg, cls=_JSONEncoder))


def _HideDefaults(cfg):
  """Hide the defaults from a given config entry.

  Args:
    cfg: A config entry.

  Returns:
    The same config entry, but without any defaults.
  """
  d = {}
  child_configs = cfg.get('child_configs')
  default = cbuildbot_config.default
  if child_configs:
    default = child_configs[0].derive(grouped=False)
    d['child_configs'] = [_HideDefaults(x) for x in child_configs]
  for k, v in cfg.iteritems():
    if k != 'child_configs' and default.get(k) != v:
      d[k] = v
  return d


def _DumpConfigPrettyJson(cfg):
  """Dump |cfg| contents in pretty JSON format.

  Args:
    cfg: A single build config.
  """
  print(json.dumps(cfg, cls=_JSONEncoder,
                   sort_keys=True, indent=4, separators=(',', ': ')))


def _DumpConfigPrettyPrint(cfg):
  """Dump |cfg| contents in pretty printer format.

  Args:
    cfg: A single build config.
  """
  pretty_printer = pprint.PrettyPrinter(indent=2)
  pretty_printer.pprint(cfg)


def _CompareConfig(old_cfg, new_cfg):
  """Compare two build configs targets, printing results.

  Args:
    old_cfg: The 'from' build config for comparison.
    new_cfg: The 'to' build config for comparison.
  """
  new_cfg = json.loads(json.dumps(new_cfg, cls=_JSONEncoder))
  for key in sorted(set(new_cfg.keys() + old_cfg.keys())):
    obj1, obj2 = old_cfg.get(key), new_cfg.get(key)
    if obj1 == obj2:
      continue
    elif obj1 is None:
      print('%s: added to config\n' % (key,))
      continue
    elif obj2 is None:
      print('%s: removed from config\n' % (key,))
      continue

    print('%s:' % (key,))

    for subkey in sorted(set(obj1.keys() + obj2.keys())):
      sobj1, sobj2 = obj1.get(subkey), obj2.get(subkey)
      if sobj1 != sobj2:
        print(' %s: %r, %r' % (subkey, sobj1, sobj2))

    print()


def GetParser():
  """Creates the argparse parser."""
  parser = commandline.ArgumentParser(description=__doc__)

  # Put options that control the mode of script into mutually exclusive group.
  mode = parser.add_mutually_exclusive_group(required=True)
  mode.add_argument('-c', '--compare', action='store',
                    type=commandline.argparse.FileType('rb'),
                    default=None, metavar='file_name',
                    help='Compare current config against a saved on disk '
                         'serialized (json) dump of a config.')
  mode.add_argument('-d', '--dump', action='store_true', default=False,
                    help='Dump the configs in JSON format.')

  parser.add_argument('--pretty', action='store_true', default=False,
                      help='If dumping, make json output human readable.')
  parser.add_argument('--for-buildbot', action='store_true', default=False,
                      help='Include the display position in data.')
  parser.add_argument('-s', '--separate-defaults', action='store_true',
                      default=False, help='Show the defaults separately.')
  parser.add_argument('config_targets', metavar='config_target', nargs='*',
                      help='Name of a cbuildbot config target.')

  return parser


def main(argv):
  parser = GetParser()
  options = parser.parse_args(argv)

  if options.pretty and not options.dump:
    parser.error('The --pretty option does not make sense without --dump')

  # Possibly translate config contents first.
  convert = lambda x: x
  if options.for_buildbot:
    convert = _InjectDisplayPosition

  config = convert(cbuildbot_config.config)

  # Separate the defaults and show them at the top. We prefix the name with
  # an underscore so that it sorts to the top.
  if options.separate_defaults:
    for k, v in config.iteritems():
      config[k] = _HideDefaults(v)
    config['_default'] = cbuildbot_config.default

  # If config_targets specified, only dump/load those.
  if options.config_targets:
    temp_config = dict()
    for c in options.config_targets:
      try:
        temp_config[c] = config[c]
      except KeyError:
        cros_build_lib.Die('No such config id: %s', c)

    config = temp_config

  if config:
    if options.dump:
      if options.pretty:
        _DumpConfigPrettyJson(config)
      else:
        _DumpConfigJson(config)
    elif options.compare:
      # Load the previously saved build config for comparison.
      old_cfg = convert(json.load(options.compare))
      _CompareConfig(old_cfg, config)

  return 0
