// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// Summarizes the information produced by the checker.
library dev_compiler.src.report;

import 'dart:math' show max;

import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/error.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
import 'package:source_span/source_span.dart';

import 'utils.dart';
import 'summary.dart';

final _checkerLogger = new Logger('dev_compiler.checker');

/// Collects errors, and then sorts them and sends them
class ErrorCollector implements AnalysisErrorListener {
  final AnalysisErrorListener listener;
  final List<AnalysisError> _errors = [];

  ErrorCollector(this.listener);

  /// Flushes errors to the log. Until this is called, errors are buffered.
  void flush() {
    // TODO(jmesserly): this code was taken from analyzer_cli.
    // sort errors
    _errors.sort((AnalysisError error1, AnalysisError error2) {
      // severity
      var severity1 = _strongModeErrorSeverity(error1);
      var severity2 = _strongModeErrorSeverity(error2);
      int compare = severity2.compareTo(severity1);
      if (compare != 0) return compare;

      // path
      compare = Comparable.compare(error1.source.fullName.toLowerCase(),
          error2.source.fullName.toLowerCase());
      if (compare != 0) return compare;

      // offset
      compare = error1.offset - error2.offset;
      if (compare != 0) return compare;

      // compare message, in worst case.
      return error1.message.compareTo(error2.message);
    });

    _errors.forEach(listener.onError);
    _errors.clear();
  }

  void onError(AnalysisError error) {
    _errors.add(error);
  }
}

ErrorSeverity _strongModeErrorSeverity(AnalysisError error) {
  // Upgrade analyzer warnings to errors.
  // TODO(jmesserly: reconcile this with analyzer_cli
  var severity = error.errorCode.errorSeverity;
  if (!error.errorCode.name.startsWith('dev_compiler.') &&
      severity == ErrorSeverity.WARNING) {
    return ErrorSeverity.ERROR;
  }
  return severity;
}

/// Simple reporter that logs checker messages as they are seen.
class LogReporter implements AnalysisErrorListener {
  final AnalysisContext _context;
  final bool useColors;
  final List<AnalysisError> _errors = [];

  LogReporter(this._context, {this.useColors: false});

  void onError(AnalysisError error) {
    var level = _severityToLevel[_strongModeErrorSeverity(error)];

    // TODO(jmesserly): figure out what to do with the error's name.
    var lineInfo = _context.computeLineInfo(error.source);
    var location = lineInfo.getLocation(error.offset);

    // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2)
    var text = new StringBuffer()
      ..write('[${errorCodeName(error.errorCode)}] ')
      ..write(error.message)
      ..write(' (${path.prettyUri(error.source.uri)}')
      ..write(', line ${location.lineNumber}, col ${location.columnNumber})');

    // TODO(jmesserly): just print these instead of sending through logger?
    _checkerLogger.log(level, text);
  }
}

// TODO(jmesserly): remove log levels, instead just use severity.
const _severityToLevel = const {
  ErrorSeverity.ERROR: Level.SEVERE,
  ErrorSeverity.WARNING: Level.WARNING,
  ErrorSeverity.INFO: Level.INFO
};

/// A reporter that gathers all the information in a [GlobalSummary].
class SummaryReporter implements AnalysisErrorListener {
  GlobalSummary result = new GlobalSummary();
  final Level _level;
  final AnalysisContext _context;

  SummaryReporter(this._context, [this._level = Level.ALL]);

  IndividualSummary _getIndividualSummary(Uri uri) {
    if (uri.path.endsWith('.html')) {
      return result.loose.putIfAbsent('$uri', () => new HtmlSummary('$uri'));
    }

    var container;
    if (uri.scheme == 'package') {
      var pname = path.split(uri.path)[0];
      result.packages.putIfAbsent(pname, () => new PackageSummary(pname));
      container = result.packages[pname].libraries;
    } else if (uri.scheme == 'dart') {
      container = result.system;
    } else {
      container = result.loose;
    }
    return container.putIfAbsent('$uri', () => new LibrarySummary('$uri'));
  }

  void onError(AnalysisError error) {
    // Only summarize messages per configured logging level
    var code = error.errorCode;
    if (_severityToLevel[code.errorSeverity] < _level) return;

    var span = _toSpan(_context, error);
    var summary = _getIndividualSummary(error.source.uri);
    if (summary is LibrarySummary) {
      summary.countSourceLines(_context, error.source);
    }
    summary.messages.add(new MessageSummary(errorCodeName(code),
        code.errorSeverity.displayName, span, error.message));
  }

  // TODO(jmesserly): fix to not depend on SourceSpan. This will be really slow
  // because it will reload source text from disk, for every single message...
  SourceSpanWithContext _toSpan(AnalysisContext context, AnalysisError error) {
    var source = error.source;
    var lineInfo = context.computeLineInfo(source);
    var content = context.getContents(source).data;
    var start = error.offset;
    var end = start + error.length;
    return createSpanHelper(lineInfo, start, end, source, content);
  }

  void clearLibrary(Uri uri) {
    (_getIndividualSummary(uri) as LibrarySummary).clear();
  }

  void clearHtml(Uri uri) {
    HtmlSummary htmlSummary = result.loose['$uri'];
    if (htmlSummary != null) htmlSummary.messages.clear();
  }
}

/// Produces a string representation of the summary.
String summaryToString(GlobalSummary summary) {
  var counter = new _Counter();
  summary.accept(counter);

  var table = new _Table();
  // Declare columns and add header
  table.declareColumn('package');
  table.declareColumn('AnalyzerError', abbreviate: true);

  var activeInfoTypes = counter.totals.keys;
  activeInfoTypes.forEach((t) => table.declareColumn(t, abbreviate: true));
  table.declareColumn('LinesOfCode', abbreviate: true);
  table.addHeader();

  // Add entries for each package
  appendCount(count) => table.addEntry(count == null ? 0 : count);
  for (var package in counter.errorCount.keys) {
    appendCount(package);
    appendCount(counter.errorCount[package]['AnalyzerError']);
    activeInfoTypes.forEach((t) => appendCount(counter.errorCount[package][t]));
    appendCount(counter.linesOfCode[package]);
  }

  // Add totals, percents and a new header for quick reference
  table.addEmptyRow();
  table.addHeader();
  table.addEntry('total');
  appendCount(counter.totals['AnalyzerError']);
  activeInfoTypes.forEach((t) => appendCount(counter.totals[t]));
  appendCount(counter.totalLinesOfCode);

  appendPercent(count, total) {
    if (count == null) count = 0;
    var value = (count * 100 / total).toStringAsFixed(2);
    table.addEntry(value);
  }

  var totalLOC = counter.totalLinesOfCode;
  table.addEntry('%');
  appendPercent(counter.totals['AnalyzerError'], totalLOC);
  activeInfoTypes.forEach((t) => appendPercent(counter.totals[t], totalLOC));
  appendCount(100);

  return table.toString();
}

/// Helper class to combine all the information in table form.
class _Table {
  int _totalColumns = 0;
  int get totalColumns => _totalColumns;

  /// Abbreviations, used to make headers shorter.
  Map<String, String> abbreviations = {};

  /// Width of each column.
  List<int> widths = <int>[];

  /// The header for each column (`header.length == totalColumns`).
  List header = [];

  /// Each row on the table. Note that all rows have the same size
  /// (`rows[*].length == totalColumns`).
  List<List> rows = [];

  /// Whether we started adding entries. Indicates that no more columns can be
  /// added.
  bool _sealed = false;

  /// Current row being built by [addEntry].
  List _currentRow;

  /// Add a column with the given [name].
  void declareColumn(String name, {bool abbreviate: false}) {
    assert(!_sealed);
    var headerName = name;
    if (abbreviate) {
      // abbreviate the header by using only the capital initials.
      headerName = name.replaceAll(new RegExp('[a-z]'), '');
      while (abbreviations[headerName] != null) headerName = "$headerName'";
      abbreviations[headerName] = name;
    }
    widths.add(max(5, headerName.length + 1) as int);
    header.add(headerName);
    _totalColumns++;
  }

  /// Add an entry in the table, creating a new row each time [totalColumns]
  /// entries are added.
  void addEntry(entry) {
    if (_currentRow == null) {
      _sealed = true;
      _currentRow = [];
    }
    int pos = _currentRow.length;
    assert(pos < _totalColumns);

    widths[pos] = max(widths[pos], '$entry'.length + 1);
    _currentRow.add('$entry');

    if (pos + 1 == _totalColumns) {
      rows.add(_currentRow);
      _currentRow = [];
    }
  }

  /// Add an empty row to divide sections of the table.
  void addEmptyRow() {
    var emptyRow = [];
    for (int i = 0; i < _totalColumns; i++) {
      emptyRow.add('-' * widths[i]);
    }
    rows.add(emptyRow);
  }

  /// Enter the header titles. OK to do so more than once in long tables.
  void addHeader() {
    rows.add(header);
  }

  /// Generates a string representation of the table to print on a terminal.
  // TODO(sigmund): add also a .csv format
  String toString() {
    var sb = new StringBuffer();
    sb.write('\n');
    for (var row in rows) {
      for (int i = 0; i < _totalColumns; i++) {
        var entry = row[i];
        // Align first column to the left, everything else to the right.
        sb.write(
            i == 0 ? entry.padRight(widths[i]) : entry.padLeft(widths[i] + 1));
      }
      sb.write('\n');
    }
    sb.write('\nWhere:\n');
    for (var id in abbreviations.keys) {
      sb.write('  $id:'.padRight(7));
      sb.write(' ${abbreviations[id]}\n');
    }
    return sb.toString();
  }
}

/// An example visitor that counts the number of errors per package and total.
class _Counter extends RecursiveSummaryVisitor {
  String _currentPackage;
  String get currentPackage =>
      _currentPackage != null ? _currentPackage : "*other*";
  var sb = new StringBuffer();
  Map<String, Map<String, int>> errorCount = <String, Map<String, int>>{};
  Map<String, int> linesOfCode = <String, int>{};
  Map<String, int> totals = <String, int>{};
  int totalLinesOfCode = 0;

  void visitGlobal(GlobalSummary global) {
    if (!global.system.isEmpty) {
      for (var lib in global.system.values) {
        lib.accept(this);
      }
    }

    if (!global.packages.isEmpty) {
      for (var lib in global.packages.values) {
        lib.accept(this);
      }
    }

    if (!global.loose.isEmpty) {
      for (var lib in global.loose.values) {
        lib.accept(this);
      }
    }
  }

  void visitPackage(PackageSummary package) {
    _currentPackage = package.name;
    super.visitPackage(package);
    _currentPackage = null;
  }

  void visitLibrary(LibrarySummary lib) {
    super.visitLibrary(lib);
    linesOfCode.putIfAbsent(currentPackage, () => 0);
    linesOfCode[currentPackage] += lib.lines;
    totalLinesOfCode += lib.lines;
  }

  visitMessage(MessageSummary message) {
    var kind = message.kind;
    errorCount.putIfAbsent(currentPackage, () => <String, int>{});
    errorCount[currentPackage].putIfAbsent(kind, () => 0);
    errorCount[currentPackage][kind]++;
    totals.putIfAbsent(kind, () => 0);
    totals[kind]++;
  }
}
