#!/usr/bin/env python3

import argparse
import glob
import json
import os

def read_reports(reports_dir):
    """Read and aggregate reports.

    We start with the base value (the one supposed to be from version control)
    and update it with each shard report.

    This way, a partial run won't lose information about tests it didn't
    run.
    """
    with open(os.path.join(reports_dir, 'rspec.json')) as base_f:
        report = json.load(base_f)
    for shard_report_path in glob.glob(
            os.path.join(reports_dir, 'rspec-*-of-*.json')):
        print("Considering shard report " + shard_report_path)
        with open(shard_report_path) as shard_f:
            report.update(json.load(shard_f))
    return report

def write_report(report, dest_path):
    """Write the report at given path

    This is logically equivalent to `open()` and `json.dump` but it
    is pretty formatted, for nicer diffs and better human readability
    """
    # direct serialization for uniformity with knapsack itself and nicer
    # diffs. Even if times always change, it will make new lines more visible
    inner_lines = ',\n'.join('  "%s": %f' % (fpath, ftime)
                             for fpath, ftime in sorted(report.items()))

    with open(dest_path, 'w') as knapf:
        knapf.write("{\n")
        knapf.write(inner_lines)
        knapf.write("\n}\n")

def main():
    parser = argparse.ArgumentParser(
        description="Reaggregate Knapsack reports done on several shards into "
        "a single report file",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )

    parser.add_argument(
        "shard_reports_dir",
    help="Path to the directory where the reports to aggregate are located."
    )
    parser.add_argument(
        '--dest',
        help="Path to the output file. Defaults to SHARD_REPORTS/rspec.json"
    )

    cl_args = parser.parse_args()
    report = read_reports(cl_args.shard_reports_dir)
    if cl_args.dest is None:
        dest_path = os.path.join(cl_args.shard_reports_dir, 'rspec.json')
    else:
        dest_path = cl_args.dest

    print("Writing aggregated report to " + dest_path)
    write_report(report, dest_path)

if __name__ == '__main__':
    main()
