// Copyright (c) 2016, 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.md file.

library testing.log;

import 'dart:io' show stdout;

import 'chain.dart' show Result, Step;

import 'suite.dart' show Suite;

import 'test_description.dart' show TestDescription;

import 'expectation.dart' show Expectation;

/// ANSI escape code for moving cursor one line up.
/// See [CSI codes](https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes).
const String cursorUpCodes = "\u001b[1A";

/// ANSI escape code for erasing the entire line.
/// See [CSI codes](https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes).
const String eraseLineCodes = "\u001b[2K";

final bool enableAnsiEscapes = stdout.supportsAnsiEscapes;

final String cursorUp = enableAnsiEscapes ? cursorUpCodes : "";

final String eraseLine = enableAnsiEscapes ? eraseLineCodes : "";

final Stopwatch wallclock = new Stopwatch()..start();

bool _isVerbose = const bool.fromEnvironment("verbose");

bool get isVerbose => _isVerbose;

void enableVerboseOutput() {
  _isVerbose = true;
}

void logTestComplete(int completed, int failed, int total, Suite suite,
    TestDescription description) {
  String message = formatProgress(completed, failed, total);
  if (suite != null) {
    message += ": ${formatTestDescription(suite, description)}";
  }
  logProgress(message);
}

void logStepStart(int completed, int failed, int total, Suite suite,
    TestDescription description, Step step) {
  String message = formatProgress(completed, failed, total);
  if (suite != null) {
    message += ": ${formatTestDescription(suite, description)} ${step.name}";
    if (step.isAsync) {
      message += "...";
    }
  }
  logProgress(message);
}

void logStepComplete(int completed, int failed, int total, Suite suite,
    TestDescription description, Step step) {
  if (!step.isAsync) return;
  String message = formatProgress(completed, failed, total);
  if (suite != null) {
    message += ": ${formatTestDescription(suite, description)} ${step.name}!";
  }
  logProgress(message);
}

void logProgress(String message) {
  if (isVerbose) {
    print(message);
  } else {
    print("$eraseLine$message$cursorUp");
  }
}

String formatProgress(int completed, int failed, int total) {
  Duration elapsed = wallclock.elapsed;
  String percent = pad((completed / total * 100.0).toStringAsFixed(1), 5);
  String good = pad(completed - failed, 5);
  String bad = pad(failed, 5);
  String minutes = pad(elapsed.inMinutes, 2, filler: "0");
  String seconds = pad(elapsed.inSeconds % 60, 2, filler: "0");
  return "[ $minutes:$seconds | $percent% | +$good | -$bad ]";
}

String formatTestDescription(Suite suite, TestDescription description) {
  return "${suite.name}/${description.shortName}";
}

void logMessage(Object message) {
  if (isVerbose) {
    print("$message");
  }
}

void logNumberedLines(String text) {
  if (isVerbose) {
    print(numberedLines(text));
  }
}

void logUnexpectedResult(Suite suite, TestDescription description,
    Result result, Set<Expectation> expectedOutcomes) {
  print("${eraseLine}UNEXPECTED: ${suite.name}/${description.shortName}");
  Uri statusFile = suite.statusFile;
  if (statusFile != null) {
    String path = statusFile.toFilePath();
    if (result.outcome == Expectation.Pass) {
      print("The test unexpectedly passed, please update $path.");
    } else {
      print("The test had the outcome ${result.outcome}, but the status file "
          "($path) allows these outcomes: ${expectedOutcomes.join(' ')}");
    }
  }
  String log = result.log;
  if (log.isNotEmpty) {
    print(log);
  }
  if (result.error != null) {
    print(result.error);
    if (result.trace != null) {
      print(result.trace);
    }
  }
}

void logSuiteComplete() {
  if (!isVerbose) {
    print("");
  }
}

void logUncaughtError(error, StackTrace stackTrace) {
  logMessage(error);
  if (stackTrace != null) {
    logMessage(stackTrace);
  }
}

String pad(Object o, int pad, {String filler: " "}) {
  String result = (filler * pad) + "$o";
  return result.substring(result.length - pad);
}

String numberedLines(String text) {
  StringBuffer result = new StringBuffer();
  int lineNumber = 1;
  List<String> lines = splitLines(text);
  int pad = "${lines.length}".length;
  String fill = " " * pad;
  for (String line in lines) {
    String paddedLineNumber = "$fill$lineNumber";
    paddedLineNumber =
        paddedLineNumber.substring(paddedLineNumber.length - pad);
    result.write("$paddedLineNumber: $line");
    lineNumber++;
  }
  return '$result';
}

List<String> splitLines(String text) {
  return text.split(new RegExp('^', multiLine: true));
}
