// Copyright (c) 2022, 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.

import 'package:args/args.dart';
import 'package:dartdoc/src/dartdoc_options.dart';
import 'package:dartdoc/src/failure.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'dartdoc_test_base.dart';
import 'src/test_descriptor_utils.dart' as d;
import 'src/utils.dart' as utils;
import 'src/utils.dart';

void main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(OptionsTest);
  });
}

@reflectiveTest
class OptionsTest extends DartdocTestBase {
  @override
  String get libraryName => 'options';

  static const packageName = 'test_package';

  Future<void> createPackage(
    String name, {
    String? dartdocOptions,
    List<d.Descriptor> libFiles = const [],
    List<d.Descriptor> files = const [],
  }) async {
    packagePath = await d.createPackage(
      packageName,
      dartdocOptions: dartdocOptions,
      libFiles: libFiles,
      files: files,
      resourceProvider: resourceProvider,
    );
    await utils.writeDartdocResources(resourceProvider);
    packageConfigProvider.addPackageToConfigFor(
        packagePath, packageName, Uri.file('$packagePath/'));
  }

  void test_faviconOption_copiesFaviconFile() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  favicon: anicon.png
''',
      libFiles: [d.file('lib.dart', '')],
      files: [d.file('anicon.png', 'Just plain text')],
    );
    await (await buildDartdoc(
      additionalArguments: [
        '--auto-include-dependencies',
        '--no-link-to-remote',
      ],
    ))
        .generateDocs();

    final faviconContent = resourceProvider
        .getFile(
            path.joinAll([packagePath, 'doc', 'static-assets', 'favicon.png']))
        .readAsStringSync();
    expect(faviconContent, contains('Just plain text'));
  }

  void test_headerOption_addsContentToIndexFile() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  header: ['extras/header.html']
''',
      libFiles: [d.file('lib.dart', '')],
      files: [
        d.dir('extras', [d.file('header.html', '<em>Header</em> things.')])
      ],
    );
    await (await buildDartdoc()).generateDocs();

    final indexContent = resourceProvider
        .getFile(path.joinAll([packagePath, 'doc', 'index.html']))
        .readAsStringSync();
    expect(indexContent, contains('<em>Header</em> things.'));
  }

  void test_footerOption_addsContentToIndexFile() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  footer: ['extras/footer.html']
''',
      libFiles: [d.file('lib.dart', '')],
      files: [
        d.dir('extras', [d.file('footer.html', '<em>Footer</em> things.')])
      ],
    );
    await (await buildDartdoc()).generateDocs();

    final indexContent = resourceProvider
        .getFile(path.joinAll([packagePath, 'doc', 'index.html']))
        .readAsStringSync();
    expect(indexContent, contains('<em>Footer</em> things.'));
  }

  void test_footerTextOption_addsTextToIndexFile() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  footerText: ['extras/footer.txt']
''',
      libFiles: [d.file('lib.dart', '')],
      files: [
        d.dir('extras', [d.file('footer.txt', 'Just footer text')])
      ],
    );
    await (await buildDartdoc()).generateDocs();

    final indexContent = resourceProvider
        .getFile(path.joinAll([packagePath, 'doc', 'index.html']))
        .readAsStringSync();
    expect(indexContent, contains('Just footer text'));
  }

  void test_excludeFooterVersionOption_doesNotDisplayVersion() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  excludeFooterVersion: true
''',
      libFiles: [d.file('lib.dart', '')],
      files: [
        d.dir('extras', [d.file('footer.txt', 'Just footer text')])
      ],
    );
    await (await buildDartdoc()).generateDocs();

    final indexContent = resourceProvider
        .getFile(path.joinAll([packagePath, 'doc', 'index.html']))
        .readAsStringSync();
    final footerRegex =
        RegExp(r'<footer>(.*\s*?\n?)+?</footer>', multiLine: true);
    // Get footer, and check for version number.
    final match = footerRegex.firstMatch(indexContent);
    if (match == null) {
      fail('Could not find footer tag in "$indexContent"');
    }
    final version = RegExp(r'(\d+\.)?(\d+\.)?(\*|\d+)');
    expect(version.hasMatch(match.group(0)!), false, reason: indexContent);
  }

  void test_examplePathPrefixOption_findsExamplesInACustomPath() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  examplePathPrefix: 'package_examples'
''',
      libFiles: [
        d.file('lib.dart', '''
/// An example in a non-default location:
///
/// {@example foo.dart}
class Foo {}
'''),
      ],
      files: [
        d.dir('package_examples', [
          d.file('foo.dart.md', '''
```
An example in an unusual dir.
```
'''),
        ]),
      ],
    );
    final packageGraph = await bootBasicPackage(
      packagePath,
      packageMetaProvider,
      packageConfigProvider,
    );
    final classFoo = packageGraph.allLocalModelElements
        .where((e) => e.isCanonical)
        .whereType<Class>()
        .firstWhere((c) => c.name == 'Foo');
    expect(classFoo.documentationAsHtml,
        contains('<code class="language-dart">An example in an unusual dir.'));
  }

  void test_formatOption_md_generatesMarkdownFiles() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {}
'''),
      ],
    );
    await (await buildDartdoc(additionalArguments: ['--format', 'md']))
        .generateDocsBase();
    final indexContent = resourceProvider
        .getFile(
            path.joinAll([packagePath, 'doc', 'library_1', 'Foo-class.md']))
        .readAsStringSync();
    expect(indexContent, contains('# Foo class'));
  }

  void test_formatOption_bad_resultsInDartdocFailure() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {}
'''),
      ],
    );
    expect(
        () => buildDartdoc(additionalArguments: ['--format', 'bad']),
        throwsA(const TypeMatcher<DartdocFailure>().having((f) => f.message,
            'message', startsWith('Unsupported output format'))));
  }

  void test_includeOption_canBeSpecifiedInOptionsFile() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  include: ["library_1", "library_2"]
''',
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {}
'''),
        d.file('library_2.dart', '''
library library_2;
class Bar {}
'''),
        d.file('library_3.dart', '''
library library_3;
class Baz {}
'''),
      ],
    );
    final packageGraph = await bootBasicPackage(
      packagePath,
      packageMetaProvider,
      packageConfigProvider,
    );
    expect(packageGraph.localPublicLibraries.map((l) => l.name),
        orderedEquals(['library_1', 'library_2']));
  }

  void test_includeCommandLineOption_overridesOptionsFileOption() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  include: ["library_1", "library_2"]
''',
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {}
'''),
        d.file('library_2.dart', '''
library library_2;
class Bar {}
'''),
        d.file('library_3.dart', '''
library library_3;
class Baz {}
'''),
      ],
    );
    final packageGraph = await bootBasicPackage(
      packagePath,
      packageMetaProvider,
      packageConfigProvider,
      additionalArguments: ['--include', 'library_3'],
    );
    expect(packageGraph.localPublicLibraries.map((l) => l.name),
        orderedEquals(['library_3']));
  }

  void test_excludeCommandLineOption_overridesOptionsFileOption() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  include: ["library_1", "library_2"]
''',
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {}
'''),
        d.file('library_2.dart', '''
library library_2;
class Bar {}
'''),
      ],
    );
    final packageGraph = await bootBasicPackage(
      packagePath,
      packageMetaProvider,
      packageConfigProvider,
      additionalArguments: ['--exclude', 'library_1'],
    );
    expect(packageGraph.localPublicLibraries.map((l) => l.name),
        orderedEquals(['library_2']));
  }

  void
      test_showUndocumentedCategoriesOption_showsUndocumentedCategories() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  showUndocumentedCategories: true
''',
      libFiles: [
        d.file('lib.dart', '''
/// {@category SomethingUndocumented}
class Foo {}
'''),
      ],
    );
    final packageGraph = await bootBasicPackage(
      packagePath,
      packageMetaProvider,
      packageConfigProvider,
    );
    final classFoo = packageGraph.allLocalModelElements
        .where((e) => e.isCanonical)
        .whereType<Class>()
        .firstWhere((c) => c.name == 'Foo');
    expect(classFoo.displayedCategories, isNotEmpty);
  }

  void test_categoryOrderOption_ordersCategories() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  categories:
    One:
      markdown: one.md
    Two:
      markdown: two.md
    Three:
      markdown: three.md
  categoryOrder: ["Three", "One", "Two"]
''',
      libFiles: [
        d.file('lib.dart', '''
library 'lib1';

/// {@category One}
class C1 {}

/// {@category Two}
class C2 {}

/// {@category Three}
class C3 {}
'''),
      ],
      files: [
        d.file('one.md', ''),
        d.file('two.md', ''),
        d.file('three.md', ''),
      ],
    );
    final packageGraph = await bootBasicPackage(
      packagePath,
      packageMetaProvider,
      packageConfigProvider,
    );
    final package = packageGraph.packages
        .firstWhere((element) => element.name == packageName);
    expect(package.documentedCategoriesSorted.map((c) => c.name),
        equals(['Three', 'One', 'Two']));
  }

  void test_categoriesNotIncludedInCategoryOrder_areOrderedAtTheEnd() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  categories:
    Three:
      markdown: three.md
    One:
      markdown: one.md
    Two:
      markdown: two.md
    Four:
      markdown: four.md
  categoryOrder: ["Two", "One"]
''',
      libFiles: [
        d.file('lib.dart', '''
library 'lib1';

/// {@category Three}
class C3 {}

/// {@category One}
class C1 {}

/// {@category Two}
class C2 {}

/// {@category Four}
class C4 {}
'''),
      ],
      files: [
        d.file('one.md', ''),
        d.file('two.md', ''),
        d.file('three.md', ''),
        d.file('four.md', ''),
      ],
    );
    final packageGraph = await bootBasicPackage(
      packagePath,
      packageMetaProvider,
      packageConfigProvider,
    );
    final package = packageGraph.packages
        .firstWhere((element) => element.name == packageName);
    expect(package.documentedCategoriesSorted.map((c) => c.name),
        equals(['Two', 'One', 'Four', 'Three']));
  }

  void test_categoriesAreOnlyTrackedWhenUsed() async {
    await createPackage(
      packageName,
      dartdocOptions: '''
dartdoc:
  categories:
    One:
      markdown: one.md
    Two:
      markdown: two.md
''',
      libFiles: [
        d.file('lib.dart', '''
library 'lib1';

/// {@category One}
class C1 {}
'''),
      ],
      files: [
        d.file('one.md', ''),
        d.file('two.md', ''),
      ],
    );
    final packageGraph = await bootBasicPackage(
      packagePath,
      packageMetaProvider,
      packageConfigProvider,
    );
    final package = packageGraph.packages
        .firstWhere((element) => element.name == packageName);
    expect(
        package.documentedCategoriesSorted.map((c) => c.name), equals(['One']));
  }

  void
      test_templatesDirOption_referencingANonExistentDirectory_resultsInDartdocFailure() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {}
'''),
      ],
    );
    expect(
        () => buildDartdoc(additionalArguments: ['--templates-dir', 'bad']),
        throwsA(const TypeMatcher<DartdocFailure>().having(
          (f) => f.message,
          'message',
          startsWith(
              'Argument --templates-dir, set to bad, resolves to missing path'),
        )));
  }

  void test_templatesDirOption_specifiesTheTemplatesToUse() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {}
'''),
      ],
      files: [
        d.dir('templates', [
          d.file('_sidebar_for_container.html', 'EMPTY'),
          d.file('_sidebar_for_library.html', 'EMPTY'),
          d.file('404error.html', 'EMPTY'),
          d.file('category.html', 'EMPTY'),
          d.file('class.html', 'CLASS FILE'),
          d.file('constructor.html', 'EMPTY'),
          d.file('enum.html', 'EMPTY'),
          d.file('extension.html', 'EMPTY'),
          d.file('function.html', 'EMPTY'),
          d.file('index.html', 'EMPTY'),
          d.file('library.html', 'EMPTY'),
          d.file('method.html', 'EMPTY'),
          d.file('mixin.html', 'EMPTY'),
          d.file('property.html', 'EMPTY'),
          d.file('top_level_property.html', 'EMPTY'),
          d.file('typedef.html', 'EMPTY'),
          d.file('search.html', 'EMPTY'),
        ]),
      ],
    );
    var customTemplatesDir = path.join(packagePath, 'templates');
    var dartdoc = await buildDartdoc(
        additionalArguments: ['--templates-dir', customTemplatesDir]);
    await dartdoc.generateDocsBase();
    final indexContent = resourceProvider
        .getFile(
            path.joinAll([packagePath, 'doc', 'library_1', 'Foo-class.html']))
        .readAsStringSync();
    expect(indexContent, contains('CLASS FILE'));
  }

  void
      test_templatesDirOptionReferencingAnEmptyDirectory_resultsInDartdocFailure() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {}
'''),
      ],
    );
    var customTemplatesDir = resourceProvider
        .newFolder(resourceProvider.pathContext
            .canonicalize(resourceProvider.convertPath('/custom_templates')))
        .path;
    expect(
        () => buildDartdoc(
            additionalArguments: ['--templates-dir', customTemplatesDir]),
        throwsA(const TypeMatcher<DartdocFailure>().having((f) => f.message,
            'message', startsWith('Missing required template file'))));
  }

  void test_quietOption_resultsInNoProgressOrOtherLogging() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {}
'''),
      ],
    );
    final dartdoc = await buildDartdoc(additionalArguments: [
      '--quiet',
    ]);
    await dartdoc.generateDocs();

    // With the `--quiet` option, nothing should be printed to stdout, and only
    // warnings should be printed to stderr.
    expect(outBuffer, isEmpty);
    expect(errBuffer.toString(), matches(RegExp(r'''
  warning: library_1 has no library level documentation comments
    from library_1: \(.*lib/library_1.dart:1:9\)
Found 1 warning and 0 errors.
''')));
  }

  void test_noGenerateDocsOption_resultsInNoLoggingAndNoGeneratedDocs() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {}
'''),
      ],
    );
    final dartdoc = await buildDartdoc(additionalArguments: [
      '--no-generate-docs',
    ]);
    await dartdoc.generateDocs();

    // With the `--no-generate-docs` option, nothing should be printed to
    // stdout, and only warnings should be printed to stderr.
    expect(outBuffer, isEmpty);
    expect(errBuffer.toString(), matches(RegExp(r'''
  warning: library_1 has no library level documentation comments
    from library_1: \(.*lib/library_1.dart:1:9\)
Found 1 warning and 0 errors.
''')));

    final outputDirectory = resourceProvider.getFolder(
      path.join(packagePath, 'doc', 'api'),
    );
    expect(outputDirectory.exists, isFalse);
  }

  void test_jsonOption_resultsInJsonOutput() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {}
'''),
      ],
    );
    await utils.writeDartdocResources(resourceProvider);
    final dartdoc = await buildDartdoc(useJson: true);
    await dartdoc.generateDocs();

    expect(
      outBuffer.toString().split('\n'),
      contains('{"level":"WARNING","message":"Found 1 warning and 0 errors."}'),
    );
    expect(errBuffer, isEmpty);
  }

  void test_nonExistentOption_resultsInFatalError() async {
    expect(
      () => utils.generatorContextFromArgv([
        '--nonexistent',
      ], packageMetaProvider),
      throwsA(isA<ArgParserException>().having(
        (e) => e.toString(),
        'toString',
        contains('Could not find an option named "nonexistent".'),
      )),
    );
  }

  void test_nonExistentInputPath_resultsInFatalError() async {
    expect(
      () => utils.generatorContextFromArgv([
        '--input',
        'non-existent',
      ], packageMetaProvider),
      throwsA(isA<DartdocFileMissing>().having(
        (e) => e.message,
        'message',
        contains(
          'Argument --input, set to non-existent, resolves to missing path:',
        ),
      )),
    );
  }

  void test_limitFilesCreated_maxFileCountIsReached() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {
  void x() {}
  void y() {}
}
'''),
      ],
    );
    final dartdoc =
        await buildDartdoc(additionalArguments: ['--max-file-count', '2']);
    await expectLater(
        dartdoc.generateDocs,
        throwsA(const TypeMatcher<DartdocFailure>().having((f) => f.message,
            'message', startsWith('Maximum file count reached: '))));
  }

  void test_limitFilesCreated_maxFileCountIsNotReached() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {
  void x() {}
  void y() {}
}
'''),
      ],
    );
    final dartdoc =
        await buildDartdoc(additionalArguments: ['--max-file-count', '2000']);
    await dartdoc.generateDocs();
  }

  void test_limitFilesCreated_maxTotalSizeIsReached() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {
  void x() {}
  void y() {}
}
'''),
      ],
    );
    final dartdoc =
        await buildDartdoc(additionalArguments: ['--max-total-size', '15000']);
    await expectLater(
        dartdoc.generateDocs,
        throwsA(const TypeMatcher<DartdocFailure>().having((f) => f.message,
            'message', startsWith('Maximum total size reached: '))));
  }

  void test_limitFilesCreated_maxTotalSizeIsNotReached() async {
    await createPackage(
      packageName,
      libFiles: [
        d.file('library_1.dart', '''
library library_1;
class Foo {
  void x() {}
  void y() {}
}
'''),
      ],
    );
    final dartdoc = await buildDartdoc(
        additionalArguments: ['--max-total-size', '15000000']);
    await dartdoc.generateDocs();
  }
}
