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

"""Show the builder layout for CrOS waterfalls."""

from __future__ import print_function

import json
import sys

from chromite.cbuildbot import config_lib
from chromite.lib import commandline


def _FormatText(data, out):
  """Formatter function for text output."""
  output = lambda *a: print(*a, file=out)

  for waterfall in sorted(data.iterkeys()):
    layout = data[waterfall]
    if not layout:
      continue

    output('== %s ==' % (waterfall,))
    for board in sorted(layout.iterkeys()):
      board_layout = layout[board]
      children = board_layout.get('children', ())
      if not children:
        output('%(name)s' % board_layout)
      else:
        output('[%(name)s]' % board_layout)
      for child in sorted(board_layout.get('children', ())):
        output('  %s' % (child,))
    output()


def _FormatJson(data, out):
  """Formatter function for JSON output."""
  json.dump(data, out, sort_keys=True)


_FORMATTERS = {
    'text': _FormatText,
    'json': _FormatJson,
}


def _ParseArguments(argv):
  parser = commandline.ArgumentParser(description=__doc__)

  parser.add_argument('--format', default='text',
                      choices=sorted(_FORMATTERS.iterkeys()),
                      help='Choose output format.')
  opts = parser.parse_args(argv)
  opts.format = _FORMATTERS[opts.format]
  opts.Freeze()
  return opts


def main(argv):
  opts = _ParseArguments(argv)

  site_config = config_lib.LoadConfigFromFile()

  layout = {}
  for config_name, config in site_config.iteritems():
    active_waterfall = config['active_waterfall']
    if not active_waterfall:
      continue

    waterfall_layout = layout.setdefault(active_waterfall, {})
    board_layout = waterfall_layout[config_name] = {
        'name': config_name,
    }

    children = config['child_configs']
    if children:
      board_layout['children'] = [c['name'] for c in children]
  opts.format(layout, sys.stdout)
