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

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

import 'package:dartdoc/dartdoc.dart';
import 'package:dartdoc/src/logging.dart';
import 'package:dartdoc/src/model.dart';
import 'package:dartdoc/src/tuple.dart';
import 'package:dartdoc/src/warnings.dart';
import 'package:path/path.dart' as pathLib;
import 'package:test/test.dart';

import 'src/utils.dart';

Uri get _currentFileUri =>
    (reflect(main) as ClosureMirror).function.location.sourceUri;
String get _testPackagePath =>
    pathLib.fromUri(_currentFileUri.resolve('../testing/test_package'));
String get _testPackageFlutterPluginPath => pathLib
    .fromUri(_currentFileUri.resolve('../testing/test_package_flutter_plugin'));

class DartdocLoggingOptionContext extends DartdocGeneratorOptionContext
    with LoggingContext {
  DartdocLoggingOptionContext(DartdocOptionSet optionSet, Directory dir)
      : super(optionSet, dir);
}

void main() {
  group('dartdoc with generators', () {
    Directory tempDir;
    List<String> outputParam;

    setUpAll(() async {
      tempDir = Directory.systemTemp.createTempSync('dartdoc.test.');
      outputParam = ['--output', tempDir.path];
      DartdocOptionSet optionSet = await DartdocOptionSet.fromOptionGenerators(
          'dartdoc', [createLoggingOptions]);
      optionSet.parseArguments([]);
      startLogging(
          new DartdocLoggingOptionContext(optionSet, Directory.current));
    });

    tearDown(() async {
      tempDir.listSync().forEach((FileSystemEntity f) {
        f.deleteSync(recursive: true);
      });
    });

    Future<Dartdoc> buildDartdoc(
        List<String> argv, Directory packageRoot) async {
      return await Dartdoc.withDefaultGenerators(await generatorContextFromArgv(
          argv..addAll(['--input', packageRoot.path])..addAll(outputParam)));
    }

    group('Option handling', () {
      Dartdoc dartdoc;
      DartdocResults results;
      PackageGraph p;

      setUpAll(() async {
        dartdoc = await buildDartdoc([], testPackageOptions);
        results = await dartdoc.generateDocsBase();
        p = results.packageGraph;
      });

      test('generator parameters', () async {
        File favicon = new File(
            pathLib.joinAll([tempDir.path, 'static-assets', 'favicon.png']));
        File index = new File(pathLib.joinAll([tempDir.path, 'index.html']));
        expect(favicon.readAsStringSync(),
            contains('Not really a png, but a test file'));
        String indexString = index.readAsStringSync();
        expect(indexString, contains('Footer things'));
        expect(indexString, contains('footer.txt data'));
        expect(indexString, contains('HTML header file'));
      });

      test('examplePathPrefix', () async {
        Class UseAnExampleHere = p.allCanonicalModelElements
            .whereType<Class>()
            .firstWhere((ModelElement c) => c.name == 'UseAnExampleHere');
        expect(
            UseAnExampleHere.documentationAsHtml,
            contains(
                'An example of an example in an unusual example location.'));
      });

      test('includeExternal and showUndocumentedCategories', () async {
        Class Something = p.allCanonicalModelElements
            .whereType<Class>()
            .firstWhere((ModelElement c) => c.name == 'Something');
        expect(Something.isPublic, isTrue);
        expect(Something.displayedCategories, isNotEmpty);
      });
    });

    test('errors generate errors even when warnings are off', () async {
      Dartdoc dartdoc = await buildDartdoc([], testPackageToolError);
      DartdocResults results = await dartdoc.generateDocsBase();
      PackageGraph p = results.packageGraph;
      Iterable<String> unresolvedToolErrors = p
          .packageWarningCounter.countedWarnings.values
          .expand<String>((Set<Tuple2<PackageWarning, String>> s) => s
              .where((Tuple2<PackageWarning, String> t) =>
                  t.item1 == PackageWarning.toolError)
              .map<String>((Tuple2<PackageWarning, String> t) => t.item2));

      expect(p.packageWarningCounter.errorCount, equals(1));
      expect(unresolvedToolErrors.length, equals(1));
      expect(unresolvedToolErrors.first,
          contains('Tool "drill" returned non-zero exit code'));
    });

    group('Invoking command-line dartdoc', () {
      String dartdocPath =
          pathLib.canonicalize(pathLib.join('bin', 'dartdoc.dart'));
      CoverageSubprocessLauncher subprocessLauncher;

      setUpAll(() {
        subprocessLauncher =
            new CoverageSubprocessLauncher('dartdoc_test-subprocesses');
      });

      tearDownAll(() async {
        await Future.wait(CoverageSubprocessLauncher.coverageResults);
      });

      test('errors cause non-zero exit when warnings are off', () async {
        expect(
            () => subprocessLauncher.runStreamed(Platform.resolvedExecutable, [
                  dartdocPath,
                  '--input=${testPackageToolError.path}',
                  '--output=${pathLib.join(tempDir.absolute.path, 'test_package_tool_error')}'
                ]),
            throwsA(const TypeMatcher<ProcessException>()));
      });

      test('errors cause non-zero exit when warnings are on', () async {
        expect(
            () => subprocessLauncher.runStreamed(Platform.resolvedExecutable, [
                  dartdocPath,
                  '--input=${testPackageToolError.path}',
                  '--output=${pathLib.join(tempDir.absolute.path, 'test_package_tool_error')}',
                  '--show-warnings',
                ]),
            throwsA(const TypeMatcher<ProcessException>()));
      });

      test('help prints command line args', () async {
        List<String> outputLines = [];
        await subprocessLauncher.runStreamed(Platform.resolvedExecutable, [dartdocPath, '--help'], perLine: outputLines.add);
        expect(outputLines, contains('Generate HTML documentation for Dart libraries.'));
        expect(outputLines.join('\n'), contains(new RegExp('^-h, --help[ ]+Show command help.', multiLine: true))) ;
      });

      test('Validate missing FLUTTER_ROOT exception is clean', () async {
        StringBuffer output = new StringBuffer();
        var args = <String>[dartdocPath];
        Future run = subprocessLauncher.runStreamed(
            Platform.resolvedExecutable, args,
            environment: new Map.from(Platform.environment)
              ..remove('FLUTTER_ROOT'),
            includeParentEnvironment: false,
            workingDirectory: _testPackageFlutterPluginPath, perLine: (s) {
          output.writeln(s);
        });
        // Asynchronous exception, but we still need the output, too.
        expect(run, throwsA(new TypeMatcher<ProcessException>()));
        try {
          await run;
        } on ProcessException catch (_) {}

        expect(
            output.toString(),
            contains(new RegExp(
                'Top level package requires Flutter but FLUTTER_ROOT environment variable not set|test_package_flutter_plugin requires the Flutter SDK, version solving failed')));
        expect(output.toString(), isNot(contains('asynchronous gap')));
      });

      test("Validate --version works", () async {
        StringBuffer output = new StringBuffer();
        var args = <String>[dartdocPath, '--version'];
        await subprocessLauncher.runStreamed(Platform.resolvedExecutable, args,
            workingDirectory: _testPackagePath,
            perLine: (s) => output.writeln(s));
        PackageMeta dartdocMeta = new PackageMeta.fromFilename(dartdocPath);
        expect(output.toString(),
            endsWith('dartdoc version: ${dartdocMeta.version}\n'));
      });

      test('Check for sample code in examples', () async {
        StringBuffer output = new StringBuffer();
        var args = <String>[
          dartdocPath,
          '--include',
          'ex',
          '--no-include-source',
          '--output',
          tempDir.path
        ];

        await subprocessLauncher.runStreamed(Platform.resolvedExecutable, args,
            workingDirectory: _testPackagePath,
            perLine: (s) => output.writeln(s));

        // Examples are reported as unfound because we (purposefully)
        // did not use --example-path-prefix above.
        final sep = '.'; // We don't care what the path separator character is
        final firstUnfoundExample =
            new RegExp('warning: lib${sep}example.dart: '
                '@example file not found.*test_package${sep}dog${sep}food.md');
        if (!output.toString().contains(firstUnfoundExample)) {
          fail('Should warn about unfound @example files');
        }
      });

      test('Validate JSON output', () async {
        var args = <String>[
          dartdocPath,
          '--include',
          'ex',
          '--no-include-source',
          '--output',
          tempDir.path,
          '--json'
        ];

        Iterable<Map> jsonValues = await subprocessLauncher.runStreamed(
            Platform.resolvedExecutable, args,
            workingDirectory: _testPackagePath);

        expect(jsonValues, isNotEmpty,
            reason: 'All STDOUT lines should be JSON-encoded maps.');
      }, timeout: new Timeout.factor(2));

      test('--footer-text includes text', () async {
        String footerTextPath =
            pathLib.join(Directory.systemTemp.path, 'footer.txt');
        new File(footerTextPath).writeAsStringSync(' footer text include ');

        var args = <String>[
          dartdocPath,
          '--footer-text=${footerTextPath}',
          '--include',
          'ex',
          '--output',
          tempDir.path
        ];

        await subprocessLauncher.runStreamed(Platform.resolvedExecutable, args,
            workingDirectory: _testPackagePath);

        File outFile = new File(pathLib.join(tempDir.path, 'index.html'));
        expect(outFile.readAsStringSync(), contains('footer text include'));
      });
    }, timeout: new Timeout.factor(3));

    group('Option handling with cross-linking', () {
      DartdocResults results;
      Package testPackageOptions;

      setUpAll(() async {
        results = await (await buildDartdoc(
                ['--link-to-remote'], testPackageOptionsImporter))
            .generateDocsBase();
        testPackageOptions = results.packageGraph.packages
            .firstWhere((Package p) => p.name == 'test_package_options');
      });

      test('linkToUrl', () async {
        Library main = testPackageOptions.allLibraries
            .firstWhere((Library l) => l.name == 'main');
        Class UseAnExampleHere = main.allClasses
            .firstWhere((Class c) => c.name == 'UseAnExampleHere');
        expect(testPackageOptions.documentedWhere,
            equals(DocumentLocation.remote));
        expect(
            UseAnExampleHere.href,
            equals(
                'https://nonexistingsuperpackage.topdomain/test_package_options/0.0.1/main/UseAnExampleHere-class.html'));
      });

      test('includeExternal works via remote', () async {
        Library unusualLibrary = testPackageOptions.allLibraries
            .firstWhere((Library l) => l.name == 'unusualLibrary');
        expect(
            unusualLibrary.allClasses
                .firstWhere((Class c) => c.name == 'Something'),
            isNotNull);
      });
    });

    test('with broken reexport chain', () async {
      Dartdoc dartdoc = await buildDartdoc([], testPackageImportExportError);
      DartdocResults results = await dartdoc.generateDocsBase();
      PackageGraph p = results.packageGraph;
      Iterable<String> unresolvedExportWarnings = p
          .packageWarningCounter.countedWarnings.values
          .expand<String>((Set<Tuple2<PackageWarning, String>> s) => s
              .where((Tuple2<PackageWarning, String> t) =>
                  t.item1 == PackageWarning.unresolvedExport)
              .map<String>((Tuple2<PackageWarning, String> t) => t.item2));

      expect(unresolvedExportWarnings.length, equals(1));
      expect(unresolvedExportWarnings.first,
          equals('"package:not_referenced_in_pubspec/library3.dart"'));
    });

    group('include/exclude parameters', () {
      test('with config file', () async {
        Dartdoc dartdoc = await buildDartdoc([], testPackageIncludeExclude);
        DartdocResults results = await dartdoc.generateDocs();
        PackageGraph p = results.packageGraph;
        expect(p.localPublicLibraries.map((l) => l.name),
            orderedEquals(['explicitly_included', 'more_included']));
      });

      test('with include command line argument', () async {
        Dartdoc dartdoc = await buildDartdoc(
            ['--include', 'another_included'], testPackageIncludeExclude);
        DartdocResults results = await dartdoc.generateDocs();
        PackageGraph p = results.packageGraph;
        expect(p.localPublicLibraries.length, equals(1));
        expect(p.localPublicLibraries.first.name, equals('another_included'));
      });

      test('with exclude command line argument', () async {
        Dartdoc dartdoc = await buildDartdoc(
            ['--exclude', 'more_included'], testPackageIncludeExclude);
        DartdocResults results = await dartdoc.generateDocs();
        PackageGraph p = results.packageGraph;
        expect(p.localPublicLibraries.length, equals(1));
        expect(
            p.localPublicLibraries.first.name, equals('explicitly_included'));
      });
    });

    test('package without version produces valid semver in docs', () async {
      Dartdoc dartdoc = await buildDartdoc([], testPackageMinimumDir);
      DartdocResults results = await dartdoc.generateDocs();
      PackageGraph p = results.packageGraph;
      expect(p.defaultPackage.version, equals('0.0.0-unknown'));
    });

    test('basic interlinking test', () async {
      Dartdoc dartdoc =
          await buildDartdoc(['--link-to-remote'], testPackageDir);
      DartdocResults results = await dartdoc.generateDocs();
      PackageGraph p = results.packageGraph;
      Package meta = p.publicPackages.firstWhere((p) => p.name == 'meta');
      TopLevelVariable useSomethingInAnotherPackage = p.publicLibraries
          .firstWhere((l) => l.name == 'fake')
          .properties
          .firstWhere((p) => p.name == 'useSomethingInAnotherPackage');
      TopLevelVariable useSomethingInTheSdk = p.publicLibraries
          .firstWhere((l) => l.name == 'fake')
          .properties
          .firstWhere((p) => p.name == 'useSomethingInTheSdk');
      expect(meta.documentedWhere, equals(DocumentLocation.remote));
      expect(
          useSomethingInAnotherPackage.modelType.linkedName,
          matches(
              '<a href=\"https://pub.dartlang.org/documentation/meta/[^\"]*/meta/Required-class.html\">Required</a>'));
      RegExp stringLink = new RegExp(
          'https://api.dartlang.org/(dev|stable|edge|be)/${Platform.version.split(' ').first}/dart-core/String-class.html">String</a>');
      expect(useSomethingInTheSdk.modelType.linkedName, contains(stringLink));
    });

    test('generate docs for ${pathLib.basename(testPackageDir.path)} works',
        () async {
      Dartdoc dartdoc = await buildDartdoc([], testPackageDir);

      DartdocResults results = await dartdoc.generateDocs();
      expect(results.packageGraph, isNotNull);

      PackageGraph packageGraph = results.packageGraph;
      Package p = packageGraph.defaultPackage;
      expect(p.name, 'test_package');
      expect(p.hasDocumentationFile, isTrue);
      // Total number of public libraries in test_package.
      expect(packageGraph.defaultPackage.publicLibraries, hasLength(12));
      expect(packageGraph.localPackages.length, equals(1));
    });

    test('generate docs for ${pathLib.basename(testPackageBadDir.path)} fails',
        () async {
      Dartdoc dartdoc = await buildDartdoc([], testPackageBadDir);

      try {
        await dartdoc.generateDocs();
        fail('dartdoc should fail on analysis errors');
      } catch (e) {
        expect(e is DartdocFailure, isTrue);
      }
    },
        skip: 'Blocked on getting analysis errors with correct interpretation'
            'from analysis_options');

    test('generate docs for a package that does not have a readme', () async {
      Dartdoc dartdoc = await buildDartdoc([], testPackageWithNoReadme);

      DartdocResults results = await dartdoc.generateDocs();
      expect(results.packageGraph, isNotNull);

      PackageGraph p = results.packageGraph;
      expect(p.defaultPackage.name, 'test_package_small');
      expect(p.defaultPackage.hasHomepage, isFalse);
      expect(p.defaultPackage.hasDocumentationFile, isFalse);
      expect(p.localPublicLibraries, hasLength(1));
    });

    test('generate docs including a single library', () async {
      Dartdoc dartdoc =
          await buildDartdoc(['--include', 'fake'], testPackageDir);

      DartdocResults results = await dartdoc.generateDocs();
      expect(results.packageGraph, isNotNull);

      PackageGraph p = results.packageGraph;
      expect(p.defaultPackage.name, 'test_package');
      expect(p.defaultPackage.hasDocumentationFile, isTrue);
      expect(p.libraries, hasLength(1));
      expect(p.libraries.map((lib) => lib.name), contains('fake'));
    });

    test('generate docs excluding a single library', () async {
      Dartdoc dartdoc =
          await buildDartdoc(['--exclude', 'fake'], testPackageDir);

      DartdocResults results = await dartdoc.generateDocs();
      expect(results.packageGraph, isNotNull);

      PackageGraph p = results.packageGraph;
      expect(p.defaultPackage.name, 'test_package');
      expect(p.defaultPackage.hasDocumentationFile, isTrue);
      expect(p.localPublicLibraries, hasLength(11));
      expect(p.localPublicLibraries.map((lib) => lib.name).contains('fake'),
          isFalse);
    });

    test('generate docs for package with embedder yaml', () async {
      Dartdoc dartdoc = await buildDartdoc([], testPackageWithEmbedderYaml);

      DartdocResults results = await dartdoc.generateDocs();
      expect(results.packageGraph, isNotNull);

      PackageGraph p = results.packageGraph;
      expect(p.defaultPackage.name, 'test_package_embedder_yaml');
      expect(p.defaultPackage.hasDocumentationFile, isFalse);
      expect(p.libraries, hasLength(3));
      expect(p.libraries.map((lib) => lib.name).contains('dart:core'), isTrue);
      expect(p.libraries.map((lib) => lib.name).contains('dart:async'), isTrue);
      expect(p.libraries.map((lib) => lib.name).contains('dart:bear'), isTrue);
      expect(p.packageMap.length, equals(2));
      // Things that do not override the core SDK belong in their own package.
      expect(p.packageMap["Dart"].isSdk, isTrue);
      expect(p.packageMap["test_package_embedder_yaml"].isSdk, isFalse);
      // Should be true once dart-lang/sdk#32707 is fixed.
      //expect(
      //    p.publicLibraries,
      //    everyElement((Library l) =>
      //        (l.element as LibraryElement).isInSdk == l.packageMeta.isSdk));
      // Ensure that we actually parsed some source by checking for
      // the 'Bear' class.
      Library dart_bear = p.packageMap["Dart"].libraries
          .firstWhere((lib) => lib.name == 'dart:bear');
      expect(
          dart_bear.allClasses.map((cls) => cls.name).contains('Bear'), isTrue);
      expect(p.packageMap["Dart"].publicLibraries, hasLength(3));
    });
  }, timeout: new Timeout.factor(8));
}
