// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:convert';

import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:path/path.dart' as path;
import 'package:platform/platform.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:snippets/snippets.dart';
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;

import '../bin/snippets.dart' as snippets_main;
import 'fake_process_manager.dart';

class FakeFlutterInformation extends FlutterInformation {
  FakeFlutterInformation(this.flutterRoot);

  final Directory flutterRoot;

  @override
  Directory getFlutterRoot() {
    return flutterRoot;
  }

  @override
  Map<String, dynamic> getFlutterInformation() {
    return <String, dynamic>{
      'flutterRoot': flutterRoot,
      'frameworkVersion': Version(2, 10, 0),
      'dartSdkVersion': Version(2, 12, 1),
    };
  }
}

void main() {
  group('Generator', () {
    late MemoryFileSystem memoryFileSystem = MemoryFileSystem();
    late FlutterRepoSnippetConfiguration configuration;
    late SnippetGenerator generator;
    late Directory tmpDir;

    void writeSkeleton(String type) {
      switch (type) {
        case 'dartpad':
          configuration.getHtmlSkeletonFile('dartpad').writeAsStringSync('''
<div>HTML Bits (DartPad-style)</div>
<iframe class="snippet-dartpad" src="https://dartpad.dev/embed-flutter.html?split=60&run=true&sample_id={{id}}&sample_channel={{channel}}"></iframe>
<div>More HTML Bits</div>
''');
        case 'sample':
        case 'snippet':
          configuration.getHtmlSkeletonFile(type).writeAsStringSync('''
<div>HTML Bits</div>
{{description}}
<pre>{{code}}</pre>
<pre>{{app}}</pre>
<div>More HTML Bits</div>
''');
      }
    }

    setUp(() {
      // Create a new filesystem.
      memoryFileSystem = MemoryFileSystem();
      tmpDir = memoryFileSystem.systemTempDirectory
          .createTempSync('flutter_snippets_test.');
      configuration = FlutterRepoSnippetConfiguration(
          flutterRoot: memoryFileSystem
              .directory(path.join(tmpDir.absolute.path, 'flutter')),
          filesystem: memoryFileSystem);
      configuration.skeletonsDirectory.createSync(recursive: true);
      <String>['dartpad', 'sample', 'snippet'].forEach(writeSkeleton);
      FlutterInformation.instance =
          FakeFlutterInformation(configuration.flutterRoot);
      generator = SnippetGenerator(
          configuration: configuration,
          filesystem: memoryFileSystem,
          flutterRoot: configuration.skeletonsDirectory.parent);
    });

    test('generates samples', () async {
      final File inputFile = memoryFileSystem
          .file(path.join(tmpDir.absolute.path, 'snippet_in.txt'))
        ..createSync(recursive: true)
        ..writeAsStringSync(r'''
A description of the sample.

On several lines.

** See code in examples/api/widgets/foo/foo_example.0.dart **
''');
      final String examplePath = path.join(configuration.flutterRoot.path, 'examples/api/widgets/foo/foo_example.0.dart');
      memoryFileSystem.file(examplePath)
        ..create(recursive: true)
        ..writeAsStringSync('''
// Copyright

// Flutter code sample for [MyElement].

void main() {
  runApp(MaterialApp(title: 'foo'));
}\n'''
        );
      final File outputFile = memoryFileSystem
          .file(path.join(tmpDir.absolute.path, 'snippet_out.txt'));
      final SnippetDartdocParser sampleParser =
          SnippetDartdocParser(memoryFileSystem);
      const String sourcePath = 'packages/flutter/lib/src/widgets/foo.dart';
      const int sourceLine = 222;
      final SourceElement element = sampleParser.parseFromDartdocToolFile(
        inputFile,
        element: 'MyElement',
        startLine: sourceLine,
        sourceFile: memoryFileSystem.file(sourcePath),
        type: 'sample',
      );

      expect(element.samples, isNotEmpty);
      element.samples.first.metadata.addAll(<String, Object?>{
        'channel': 'stable',
      });
      final String code = generator.generateCode(
        element.samples.first,
        output: outputFile,
      );
      expect(code, contains("runApp(MaterialApp(title: 'foo'));"));
      final String html = generator.generateHtml(
        element.samples.first,
      );
      expect(html, contains('<div>HTML Bits</div>'));
      expect(html, contains('<div>More HTML Bits</div>'));
      expect(html, contains(r'''runApp(MaterialApp(title: &#39;foo&#39;));'''));
      expect(html, isNot(contains('sample_channel=stable')));
      expect(
          html,
          contains('A description of the sample.\n'
              '\n'
              'On several lines.{@inject-html}</div>'));
      expect(html, contains('void main() {'));

      final String outputContents = outputFile.readAsStringSync();
      expect(outputContents, contains('void main() {'));
    });

    test('generates snippets', () async {
      final File inputFile = memoryFileSystem
          .file(path.join(tmpDir.absolute.path, 'snippet_in.txt'))
        ..createSync(recursive: true)
        ..writeAsStringSync(r'''
A description of the snippet.

On several lines.

```code
void main() {
  print('The actual $name.');
}
```
''');

      final SnippetDartdocParser sampleParser =
          SnippetDartdocParser(memoryFileSystem);
      const String sourcePath = 'packages/flutter/lib/src/widgets/foo.dart';
      const int sourceLine = 222;
      final SourceElement element = sampleParser.parseFromDartdocToolFile(
        inputFile,
        element: 'MyElement',
        startLine: sourceLine,
        sourceFile: memoryFileSystem.file(sourcePath),
        type: 'snippet',
      );
      expect(element.samples, isNotEmpty);
      element.samples.first.metadata.addAll(<String, Object>{
        'channel': 'stable',
      });
      final String code = generator.generateCode(element.samples.first);
      expect(code, contains('// A description of the snippet.'));
      final String html = generator.generateHtml(element.samples.first);
      expect(html, contains('<div>HTML Bits</div>'));
      expect(html, contains('<div>More HTML Bits</div>'));
      expect(html, contains(r'  print(&#39;The actual $name.&#39;);'));
      expect(
          html,
          contains(
              '<div class="snippet-description">{@end-inject-html}A description of the snippet.\n\n'
              'On several lines.{@inject-html}</div>\n'));
      expect(html, contains('main() {'));
    });

    test('generates dartpad samples', () async {
      final File inputFile = memoryFileSystem
          .file(path.join(tmpDir.absolute.path, 'snippet_in.txt'))
        ..createSync(recursive: true)
        ..writeAsStringSync(r'''
A description of the snippet.

On several lines.

** See code in examples/api/widgets/foo/foo_example.0.dart **
''');
      final String examplePath = path.join(configuration.flutterRoot.path, 'examples/api/widgets/foo/foo_example.0.dart');
      memoryFileSystem.file(examplePath)
        ..create(recursive: true)
        ..writeAsStringSync('''
// Copyright

// Flutter code sample for [MyElement].

void main() {
  runApp(MaterialApp(title: 'foo'));
}\n'''
        );

      final SnippetDartdocParser sampleParser =
          SnippetDartdocParser(memoryFileSystem);
      const String sourcePath = 'packages/flutter/lib/src/widgets/foo.dart';
      const int sourceLine = 222;
      final SourceElement element = sampleParser.parseFromDartdocToolFile(
        inputFile,
        element: 'MyElement',
        startLine: sourceLine,
        sourceFile: memoryFileSystem.file(sourcePath),
        type: 'dartpad',
      );
      expect(element.samples, isNotEmpty);
      element.samples.first.metadata.addAll(<String, Object>{
        'channel': 'stable',
      });
      final String code = generator.generateCode(element.samples.first);
      expect(code, contains("runApp(MaterialApp(title: 'foo'));"));
      final String html = generator.generateHtml(element.samples.first);
      expect(html, contains('<div>HTML Bits (DartPad-style)</div>'));
      expect(html, contains('<div>More HTML Bits</div>'));
      expect(
          html,
          contains(
              '<iframe class="snippet-dartpad" src="https://dartpad.dev/embed-flutter.html?split=60&run=true&sample_id=MyElement.0&sample_channel=stable"></iframe>\n'));
    });

    test('generates sample metadata', () async {
      final File inputFile = memoryFileSystem
          .file(path.join(tmpDir.absolute.path, 'snippet_in.txt'))
        ..createSync(recursive: true)
        ..writeAsStringSync(r'''
A description of the snippet.

On several lines.

```dart
void main() {
  print('The actual $name.');
}
```
''');

      final File outputFile = memoryFileSystem
          .file(path.join(tmpDir.absolute.path, 'snippet_out.dart'));
      final File expectedMetadataFile = memoryFileSystem
          .file(path.join(tmpDir.absolute.path, 'snippet_out.json'));

      final SnippetDartdocParser sampleParser =
          SnippetDartdocParser(memoryFileSystem);
      const String sourcePath = 'packages/flutter/lib/src/widgets/foo.dart';
      const int sourceLine = 222;
      final SourceElement element = sampleParser.parseFromDartdocToolFile(
        inputFile,
        element: 'MyElement',
        startLine: sourceLine,
        sourceFile: memoryFileSystem.file(sourcePath),
        type: 'sample',
      );
      expect(element.samples, isNotEmpty);
      element.samples.first.metadata
          .addAll(<String, Object>{'channel': 'stable'});
      generator.generateCode(element.samples.first, output: outputFile);
      expect(expectedMetadataFile.existsSync(), isTrue);
      final Map<String, dynamic> json =
          jsonDecode(expectedMetadataFile.readAsStringSync())
              as Map<String, dynamic>;
      expect(json['id'], equals('MyElement.0'));
      expect(json['channel'], equals('stable'));
      expect(json['file'], equals('snippet_out.dart'));
      expect(json['description'],
          equals('A description of the snippet.\n\nOn several lines.'));
      expect(json['sourcePath'],
          equals('packages/flutter/lib/src/widgets/foo.dart'));
    });
  });

  group('snippets command line argument test', () {
    late MemoryFileSystem memoryFileSystem = MemoryFileSystem();
    late Directory tmpDir;
    late Directory flutterRoot;
    late FakeProcessManager fakeProcessManager;

    setUp(() {
      fakeProcessManager = FakeProcessManager();
      memoryFileSystem = MemoryFileSystem();
      tmpDir = memoryFileSystem.systemTempDirectory
          .createTempSync('flutter_snippets_test.');
      flutterRoot = memoryFileSystem
          .directory(path.join(tmpDir.absolute.path, 'flutter'))
        ..createSync(recursive: true);
    });

    test('command line arguments are parsed and passed to generator', () {
      final FakePlatform platform = FakePlatform(environment: <String, String>{
        'PACKAGE_NAME': 'dart:ui',
        'LIBRARY_NAME': 'library',
        'ELEMENT_NAME': 'element',
        'FLUTTER_ROOT': flutterRoot.absolute.path,
        // The details here don't really matter other than the flutter root.
        'FLUTTER_VERSION': '''
      {
        "frameworkVersion": "2.5.0-6.0.pre.55",
        "channel": "use_snippets_pkg",
        "repositoryUrl": "git@github.com:flutter/flutter.git",
        "frameworkRevision": "fec4641e1c88923ecd6c969e2ff8a0dd12dc0875",
        "frameworkCommitDate": "2021-08-11 15:19:48 -0700",
        "engineRevision": "d8bbebed60a77b3d4fe9c840dc94dfbce159d951",
        "dartSdkVersion": "2.14.0 (build 2.14.0-393.0.dev)",
        "flutterRoot": "${flutterRoot.absolute.path}"
      }''',
      });
      final FlutterInformation flutterInformation = FlutterInformation(
        filesystem: memoryFileSystem,
        processManager: fakeProcessManager,
        platform: platform,
      );
      FlutterInformation.instance = flutterInformation;
      MockSnippetGenerator mockSnippetGenerator = MockSnippetGenerator();
      snippets_main.snippetGenerator = mockSnippetGenerator;
      String errorMessage = '';
      errorExit = (String message) {
        errorMessage = message;
      };

      snippets_main.platform = platform;
      snippets_main.filesystem = memoryFileSystem;
      snippets_main.processManager = fakeProcessManager;
      final File input = memoryFileSystem
          .file(tmpDir.childFile('input.snippet'))
        ..writeAsString('/// Test file');
      snippets_main.main(
          <String>['--input=${input.absolute.path}']);

      final Map<String, dynamic> metadata =
          mockSnippetGenerator.sample.metadata;
      // Ignore the channel, because channel is really just the branch, and will be
      // different on development workstations.
      metadata.remove('channel');
      expect(
          metadata,
          equals(<String, dynamic>{
            'id': 'dart_ui.library.element',
            'element': 'element',
            'sourcePath': 'unknown.dart',
            'sourceLine': 1,
            'serial': '',
            'package': 'dart:ui',
            'library': 'library',
          }));

      snippets_main.main(<String>[]);
      expect(
          errorMessage,
          equals(
              'The --input option must be specified, either on the command line, or in the INPUT environment variable.'));
      errorMessage = '';

      snippets_main
          .main(<String>['--input=${input.absolute.path}', '--type=snippet']);
      expect(errorMessage, equals(''));
      errorMessage = '';

      mockSnippetGenerator = MockSnippetGenerator();
      snippets_main.snippetGenerator = mockSnippetGenerator;
      snippets_main.main(<String>[
        '--input=${input.absolute.path}',
        '--type=snippet',
        '--no-format-output'
      ]);
      expect(mockSnippetGenerator.formatOutput, equals(false));
      errorMessage = '';

      input.deleteSync();
      snippets_main.main(
          <String>['--input=${input.absolute.path}']);
      expect(errorMessage,
          equals('The input file ${input.absolute.path} does not exist.'));
      errorMessage = '';
    });
  });
}

class MockSnippetGenerator extends SnippetGenerator {
  late CodeSample sample;
  File? output;
  String? copyright;
  String? description;
  late bool formatOutput;
  late bool addSectionMarkers;
  late bool includeAssumptions;

  @override
  String generateCode(
    CodeSample sample, {
    File? output,
    String? copyright,
    String? description,
    bool formatOutput = true,
    bool addSectionMarkers = false,
    bool includeAssumptions = false,
  }) {
    this.sample = sample;
    this.output = output;
    this.copyright = copyright;
    this.description = description;
    this.formatOutput = formatOutput;
    this.addSectionMarkers = addSectionMarkers;
    this.includeAssumptions = includeAssumptions;

    return '';
  }

  @override
  String generateHtml(CodeSample sample) {
    return '';
  }
}
