#!/usr/bin/env python3
# Copyright 2017 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import print_function

import json
import os
import six
import sys

import merge_api
import results_merger


def StandardIsolatedScriptMerge(output_json, summary_json, jsons_to_merge):
  """Merge the contents of one or more results JSONs into a single JSON.

  Args:
    output_json: A path to a JSON file to which the merged results should be
      written.
    jsons_to_merge: A list of paths to JSON files that should be merged.
  """
  # summary.json is produced by swarming client itself. We are mostly interested
  # in the number of shards.
  try:
    with open(summary_json) as f:
      summary = json.load(f)
  except (IOError, ValueError):
    print((
        'summary.json is missing or can not be read',
        'Something is seriously wrong with swarming client or the bot.'),
        file=sys.stderr)
    return 1

  missing_shards = []
  shard_results_list = []
  for index, result in enumerate(summary['shards']):
    output_path = None
    if result:
      output_path = find_shard_output_path(index, result.get('task_id'),
                                           jsons_to_merge)
    if not output_path:
      missing_shards.append(index)
      continue

    with open(output_path) as f:
      try:
        json_contents = json.load(f)
      except ValueError as e:
        six.raise_from(ValueError(
              'Failed to parse JSON from %s' % output_path), e)
      shard_results_list.append(json_contents)

  merged_results = results_merger.merge_test_results(shard_results_list)
  if missing_shards:
    merged_results['missing_shards'] = missing_shards
    if 'global_tags' not in merged_results:
      merged_results['global_tags'] = []
    merged_results['global_tags'].append('UNRELIABLE_RESULTS')

  with open(output_json, 'w') as f:
    json.dump(merged_results, f)

  return 0


def find_shard_output_path(index, task_id, jsons_to_merge):
  """Finds the shard matching the index/task-id.

  Args:
    index: The index of the shard to load data for, this is for old api.
    task_id: The directory of the shard to load data for, this is for new api.
    jsons_to_merge: A container of file paths for shards that emitted output.

  Returns:
    * The matching path, or None
  """
  # 'output.json' is set in swarming/api.py, gtest_task method.
  matching_json_files = [
      j for j in jsons_to_merge
      if (os.path.basename(j) == 'output.json' and
          (os.path.basename(os.path.dirname(j)) == str(index) or
           os.path.basename(os.path.dirname(j)) == task_id))]

  if not matching_json_files:
    print('shard %s test output missing' % index, file=sys.stderr)
    return None
  if len(matching_json_files) > 1:
    print('duplicate test output for shard %s' % index, file=sys.stderr)
    return None

  return matching_json_files[0]


def main(raw_args):
  parser = merge_api.ArgumentParser()
  args = parser.parse_args(raw_args)
  return StandardIsolatedScriptMerge(
      args.output_json, args.summary_json, args.jsons_to_merge)


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