// 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.

library dartdoc.compare_output_test;

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:mirrors';

import 'package:path/path.dart' as p;
import 'package:test/test.dart';

import 'package:which/which.dart';

Uri get _currentFileUri =>
    (reflect(main) as ClosureMirror).function.location.sourceUri;

String get _testPackageDocsPath =>
    p.fromUri(_currentFileUri.resolve('../test_package_docs'));

String get _testPackagePath =>
    p.fromUri(_currentFileUri.resolve('../test_package'));

void main() {
  group('compare outputs', () {
    Directory tempDir;

    setUp(() {
      tempDir = Directory.systemTemp.createTempSync('dartdoc.test.');
    });

    tearDown(() {
      if (tempDir != null) {
        tempDir.deleteSync(recursive: true);
      }
    });

    test("Validate html output of test_package", () async {
      if (Platform.isWindows) {
        print("Tests are being run via `all.dart`, which means onPlatform "
            "argument is ignored. Skipping on Windows to avoid parsing git output");
        return;
      }

      var dartdocBin =
          p.fromUri(_currentFileUri.resolve('../bin/dartdoc.dart'));

      // NOTE: excluding `fake` library because it contains exported code
      //       from the SDK that has changed between 1.12 and 1.13
      // This must match the content in `grind to update test_package_docs`

      var args = <String>[
        dartdocBin,
        '--no-include-source',
        '--output',
        tempDir.path,
        '--exclude',
        'fake'
      ];

      var result =
          Process.runSync('dart', args, workingDirectory: _testPackagePath);

      if (result.exitCode != 0) {
        print(result.exitCode);
        print(result.stdout);
        print(result.stderr);
        fail('dartdoc failed');
      }

      var gitPath = await _gitBinPath();

      args = <String>[
        'diff',
        '--no-index',
        '--name-status',
        '--no-color',
        _testPackageDocsPath,
        tempDir.path
      ];

      result = Process.runSync(gitPath, args);

      if (result.exitCode == 0) return;

      var things =
          _parseOutput(result.stdout, _testPackageDocsPath, tempDir.path);

      if (things.isEmpty) return;

      var message = <String>["There were differences:"];

      things.forEach((k, v) {
        if (v == 'M') {
          // If the discovered diff is a modification of a file, then
          // run `git diff` and add the output to the fail message.
          args = <String>[
            'diff',
            '--no-index',
            '--no-color',
            p.join(_testPackageDocsPath, k),
            p.join(tempDir.path, k)
          ];
          result = Process.runSync(gitPath, args);
          assert(result.exitCode != 0);
          // TODO(keertip): remove once 1.14 is stable; noSuchMethod documentation
          // has changed from 1.13 to 1.14.
          if (!result.stdout.contains('noSuchMethod')) {
            message.add("$v\t$k");
            message.add(result.stdout);
          }
        }
      });

      if (message.length == 1) return;

      message.addAll([
        '',
        "If there have been changes to generation"
            " you may need to run `grind update-test-package-docs` again."
      ]);

      fail(message.join('\n'));
    });
  }, onPlatform: {'windows': new Skip('Avoiding parsing git output')});
}

Map<String, String> _parseOutput(
    String input, String sourcePath, String tempPath) {
  var values = <String, String>{};
  for (var line in LineSplitter.split(input)) {
    Match match = _nameStatusLineRegexp.firstMatch(line);

    var type = match[1];
    var path = match[2];

    if (_filesToIgnore.any((i) => p.basename(path) == i)) {
      continue;
    }

    if (type == 'A') {
      expect(p.isWithin(tempPath, path), isTrue,
          reason: '`${path}` should be within ${tempPath}');
      path = p.relative(path, from: tempPath);
    } else {
      expect(p.isWithin(sourcePath, path), isTrue,
          reason: '`${path}` should be within ${sourcePath}');
      path = p.relative(path, from: sourcePath);
    }

    values[path] = type;
  }

  return values;
}

const List<String> _filesToIgnore = const <String>['.DS_Store'];

final _nameStatusLineRegexp = new RegExp(r'(\w)\t(.+)');

const _gitBinName = 'git';

String _gitCache;

Future<String> _gitBinPath() async {
  if (_gitCache == null) {
    _gitCache = await which(_gitBinName);
  }
  return _gitCache;
}
