// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// A script for reading an lcov file and printing out the coverage information
// to the console, in a human-friendly table format.

import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:math';

Future<Null> main(List<String> args) async {
  // Expect to get exactly one argument.
  if (args.length != 1) {
    stderr.writeln('Usage: dart report_coverage.dart <path_to_lcov_info>');
    exit(1);
  }

  // Existence check.
  File reportFile = File(args[0]);
  if (!await reportFile.exists()) {
    stderr.writeln('The file ${args[0]} does not exist.');
    exit(1);
  }

  // Process line by line.
  String currentFile;
  Set<String> files = SplayTreeSet<String>();
  Map<String, int> totalLines = HashMap<String, int>();
  Map<String, int> coveredLines = HashMap<String, int>();

  await reportFile
      .openRead()
      .transform(utf8.decoder)
      .transform(const LineSplitter())
      .listen((String line) {
    if (line.startsWith('SF:')) {
      // Process a new source file.
      assert(currentFile == null);
      currentFile = line.substring(3);
      files.add(currentFile);
      totalLines[currentFile] = 0;
      coveredLines[currentFile] = 0;
    } else if (line.startsWith('DA:')) {
      // Add this line info to the map.
      List<String> tokens = line.substring(3).split(',');
      assert(tokens.length == 2);
      totalLines[currentFile]++;
      coveredLines[currentFile] += int.parse(tokens[1]) > 0 ? 1 : 0;
    } else if (line == 'end_of_record') {
      currentFile = null;
    } else {
      stderr.writeln('Unknown directive: $line');
      exit(1);
    }
  }).asFuture();

  // Report to console.
  TableWriter writer = TableWriter(stdout)
    ..setHeaders(<Object>['Filepath', 'Covered', 'Total', 'Percentage'])
    ..setRightAlignment(<bool>[false, true, true, true]);
  for (String file in files) {
    writer.addRow(<Object>[
      file,
      coveredLines[file],
      totalLines[file],
      '${_getPercentage(coveredLines[file], totalLines[file])}%',
    ]);
  }

  // Last line for total.
  int totalCoveredLines = coveredLines.values.fold(0, (int a, int b) => a + b);
  int totalTotalLines = totalLines.values.fold(0, (int a, int b) => a + b);
  writer
    ..setFooters(<Object>[
      'Total',
      totalCoveredLines,
      totalTotalLines,
      '${_getPercentage(totalCoveredLines, totalTotalLines)}%',
    ])
    ..render();
}

double _getPercentage(int covered, int total) {
  return (covered * 1000 / total).roundToDouble() / 10;
}

/// A utility class for pretty-printing the data
class TableWriter {
  /// Creates a new [TableWriter] instance with the specified output target.
  TableWriter(Stdout out) : _out = out;

  final Stdout _out;
  final List<int> _colLen = <int>[];
  final List<List<String>> _rows = <List<String>>[];
  List<String> _headers;
  List<String> _footers;
  List<bool> _rightAlignments;

  /// Sets the header strings.
  void setHeaders(List<Object> headers) {
    assert(_headers == null);
    _headers = _processRow(headers);
  }

  /// Sets the footer strings.
  void setFooters(List<Object> footers) {
    assert(_footers == null);
    _footers = _processRow(footers);
  }

  // ignore: use_setters_to_change_properties
  /// Sets whether each column needs to be right aligned.
  void setRightAlignment(List<bool> rightAlignments) {
    _rightAlignments = rightAlignments;
  }

  /// Adds a new data row.
  void addRow(List<Object> row) {
    _rows.add(_processRow(row));
  }

  /// Render the table to the target provided to the constructor.
  void render() {
    if (_headers != null) {
      _renderRow(_headers);
      _renderSeparationLine();
    }

    _rows.forEach(_renderRow);

    if (_footers != null) {
      _renderSeparationLine();
      _renderRow(_footers);
    }
  }

  List<String> _processRow(List<Object> row) {
    while (row.length > _colLen.length) {
      _colLen.add(0);
    }

    List<String> stringRow = row.map((Object x) => x.toString()).toList();
    for (int i = 0; i < stringRow.length; ++i) {
      _colLen[i] = max(_colLen[i], stringRow[i].length);
    }

    return stringRow;
  }

  void _renderRow(List<String> row) {
    for (int i = 0; i < row.length; ++i) {
      if (i > 0) {
        _out.write(' ');
      }

      if (_shouldBeRightAligned(i)) {
        _out..write(' ' * (_colLen[i] - row[i].length))..write(row[i]);
      } else {
        _out..write(row[i])..write(' ' * (_colLen[i] - row[i].length));
      }
    }
    _out.writeln();
  }

  void _renderSeparationLine() {
    int count = _colLen.fold(_colLen.length - 1, (int x, int y) => x + y);
    _out.writeln('=' * count);
  }

  bool _shouldBeRightAligned(int colIndex) {
    if (_rightAlignments != null && colIndex < _rightAlignments.length) {
      return _rightAlignments[colIndex];
    }

    return false;
  }
}
