// 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:async';

import 'package:args/command_runner.dart';
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/create.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/globals.dart' as globals;

import '../src/common.dart';
import '../src/context.dart';
import '../src/test_flutter_command_runner.dart';

void main() {
  late Directory tempDir;
  late Directory projectDir;

  setUpAll(() async {
    Cache.disableLocking();
    await _ensureFlutterToolsSnapshot();
  });

  setUp(() {
    tempDir = globals.fs.systemTempDirectory
        .createTempSync('flutter_tools_generated_plugin_registrant_test.');
    projectDir = tempDir.childDirectory('flutter_project');
  });

  tearDown(() {
    tryToDelete(tempDir);
  });

  tearDownAll(() async {
    await _restoreFlutterToolsSnapshot();
  });

  testUsingContext('generated plugin registrant passes analysis', () async {
    await _createProject(projectDir, <String>[]);
    // We need a dependency so the plugin registrant is not completely empty.
    await _editPubspecFile(projectDir, _addDependencyEditor('shared_preferences',
        version: '^2.0.0'));
    // The plugin registrant is created on build...
    await _buildWebProject(projectDir);

    // Find the web_plugin_registrant, now that it lives outside "lib":
    final Directory buildDir = projectDir
        .childDirectory('.dart_tool/flutter_build')
        .listSync()
        .firstWhere((FileSystemEntity entity) => entity is Directory) as Directory;

    // Ensure the file exists, and passes analysis.
    final File registrant = buildDir.childFile('web_plugin_registrant.dart');
    expect(registrant, exists);
    await _analyzeEntity(registrant);

    // Ensure the contents match what we expect for a non-empty plugin registrant.
    final String contents = registrant.readAsStringSync();
    expect(contents, contains('// @dart = 2.13'));
    expect(contents, contains("import 'package:shared_preferences_web/shared_preferences_web.dart';"));
    expect(contents, contains('void registerPlugins([final Registrar? pluginRegistrar]) {'));
    expect(contents, contains('SharedPreferencesPlugin.registerWith(registrar);'));
    expect(contents, contains('registrar.registerMessageHandler();'));
  }, overrides: <Type, Generator>{
    Pub: () => Pub(
          fileSystem: globals.fs,
          logger: globals.logger,
          processManager: globals.processManager,
          usage: globals.flutterUsage,
          botDetector: globals.botDetector,
          platform: globals.platform,
        ),
  });

  testUsingContext('generated plugin registrant passes analysis without null safety', () async {
    await _createProject(projectDir, <String>[]);
    // We need a dependency so the plugin registrant is not completely empty.
    await _editPubspecFile(projectDir,
      _composeEditors(<PubspecEditor>[
        _addDependencyEditor('shared_preferences', version: '^2.0.0'),

        // This turns null safety off
        _setDartSDKVersionEditor('>=2.11.0 <3.0.0'),
      ]));

    // The generated main.dart file has a bunch of stuff that is invalid without null safety, so
    // replace it with a no-op dummy main file. We aren't testing it in this scenario anyway.
    await _replaceMainFile(projectDir, 'void main() {}');

    // The plugin registrant is created on build...
    await _buildWebProject(projectDir);

    // Find the web_plugin_registrant, now that it lives outside "lib":
    final Directory buildDir = projectDir
        .childDirectory('.dart_tool/flutter_build')
        .listSync()
        .firstWhere((FileSystemEntity entity) => entity is Directory) as Directory;

    // Ensure the file exists, and passes analysis.
    final File registrant = buildDir.childFile('web_plugin_registrant.dart');
    expect(registrant, exists);
    await _analyzeEntity(registrant);

    // Ensure the contents match what we expect for a non-empty plugin registrant.
    final String contents = registrant.readAsStringSync();
    expect(contents, contains('// @dart = 2.13'));
    expect(contents, contains("import 'package:shared_preferences_web/shared_preferences_web.dart';"));
    expect(contents, contains('void registerPlugins([final Registrar? pluginRegistrar]) {'));
    expect(contents, contains('SharedPreferencesPlugin.registerWith(registrar);'));
    expect(contents, contains('registrar.registerMessageHandler();'));
  }, overrides: <Type, Generator>{
    Pub: () => Pub(
          fileSystem: globals.fs,
          logger: globals.logger,
          processManager: globals.processManager,
          usage: globals.flutterUsage,
          botDetector: globals.botDetector,
          platform: globals.platform,
        ),
  });


  testUsingContext('(no-op) generated plugin registrant passes analysis', () async {
    await _createProject(projectDir, <String>[]);
    // No dependencies on web plugins this time!
    await _buildWebProject(projectDir);

    // Find the web_plugin_registrant, now that it lives outside "lib":
    final Directory buildDir = projectDir
        .childDirectory('.dart_tool/flutter_build')
        .listSync()
        .firstWhere((FileSystemEntity entity) => entity is Directory) as Directory;

    // Ensure the file exists, and passes analysis.
    final File registrant = buildDir.childFile('web_plugin_registrant.dart');
    expect(registrant, exists);
    await _analyzeEntity(registrant);

    // Ensure the contents match what we expect for an empty (noop) plugin registrant.
    final String contents = registrant.readAsStringSync();
    expect(contents, contains('void registerPlugins() {}'));
  }, overrides: <Type, Generator>{
    Pub: () => Pub(
          fileSystem: globals.fs,
          logger: globals.logger,
          processManager: globals.processManager,
          usage: globals.flutterUsage,
          botDetector: globals.botDetector,
          platform: globals.platform,
        ),
  });

  // See: https://github.com/dart-lang/dart-services/pull/874
  testUsingContext('generated plugin registrant for dartpad is created on pub get', () async {
    await _createProject(projectDir, <String>[]);
    await _editPubspecFile(projectDir,
      _addDependencyEditor('shared_preferences', version: '^2.0.0'));
    // The plugin registrant for dartpad is created on flutter pub get.
    await _doFlutterPubGet(projectDir);

    final File registrant = projectDir
        .childDirectory('.dart_tool/dartpad')
        .childFile('web_plugin_registrant.dart');

    // Ensure the file exists, and passes analysis.
    expect(registrant, exists);
    await _analyzeEntity(registrant);

    // Assert the full build hasn't happened!
    final Directory buildDir = projectDir.childDirectory('.dart_tool/flutter_build');
    expect(buildDir, isNot(exists));
  }, overrides: <Type, Generator>{
    Pub: () => Pub(
          fileSystem: globals.fs,
          logger: globals.logger,
          processManager: globals.processManager,
          usage: globals.flutterUsage,
          botDetector: globals.botDetector,
          platform: globals.platform,
        ),
  });

  testUsingContext(
      'generated plugin registrant ignores lines longer than 80 chars',
      () async {
    await _createProject(projectDir, <String>[]);
    await _addAnalysisOptions(
        projectDir, <String>['lines_longer_than_80_chars']);
    await _createProject(tempDir.childDirectory('test_plugin'), <String>[
      '--template=plugin',
      '--platforms=web',
      '--project-name',
      'test_web_plugin_with_a_purposefully_extremely_long_package_name',
    ]);
    // The line for the test web plugin (`  TestWebPluginWithAPurposefullyExtremelyLongPackageNameWeb.registerWith(registrar);`)
    // exceeds 80 chars.
    // With the above lint rule added, we want to ensure that the `generated_plugin_registrant.dart`
    // file does not fail analysis (this is a regression test - an ignore was
    // added to cover this case).
    await _editPubspecFile(
      projectDir,
      _addDependencyEditor(
        'test_web_plugin_with_a_purposefully_extremely_long_package_name',
        path: '../test_plugin',
      )
    );
    // The plugin registrant is only created after a build...
    await _buildWebProject(projectDir);

    // Find the web_plugin_registrant, now that it lives outside "lib":
    final Directory buildDir = projectDir
        .childDirectory('.dart_tool/flutter_build')
        .listSync()
        .firstWhere((FileSystemEntity entity) => entity is Directory) as Directory;

    expect(
      buildDir.childFile('web_plugin_registrant.dart'),
      exists,
    );
    await _analyzeEntity(buildDir.childFile('web_plugin_registrant.dart'));
  }, overrides: <Type, Generator>{
    Pub: () => Pub(
          fileSystem: globals.fs,
          logger: globals.logger,
          processManager: globals.processManager,
          usage: globals.flutterUsage,
          botDetector: globals.botDetector,
          platform: globals.platform,
        ),
  });
}

Future<void> _ensureFlutterToolsSnapshot() async {
  final String flutterToolsPath = globals.fs.path.absolute(globals.fs.path.join(
    'bin',
    'flutter_tools.dart',
  ));
  final String flutterToolsSnapshotPath = globals.fs.path.absolute(
    globals.fs.path.join(
      '..',
      '..',
      'bin',
      'cache',
      'flutter_tools.snapshot',
    ),
  );
  final String dotPackages = globals.fs.path.absolute(globals.fs.path.join(
    '.dart_tool/package_config.json',
  ));

  final File snapshotFile = globals.fs.file(flutterToolsSnapshotPath);
  if (snapshotFile.existsSync()) {
    snapshotFile.renameSync('$flutterToolsSnapshotPath.bak');
  }

  final List<String> snapshotArgs = <String>[
    '--snapshot=$flutterToolsSnapshotPath',
    '--packages=$dotPackages',
    flutterToolsPath,
  ];
  final ProcessResult snapshotResult = await Process.run(
    '../../bin/cache/dart-sdk/bin/dart',
    snapshotArgs,
  );
  printOnFailure('Output of dart ${snapshotArgs.join(" ")}:');
  printOnFailure(snapshotResult.stdout.toString());
  printOnFailure(snapshotResult.stderr.toString());
  expect(snapshotResult.exitCode, 0);
}

Future<void> _restoreFlutterToolsSnapshot() async {
  final String flutterToolsSnapshotPath = globals.fs.path.absolute(
    globals.fs.path.join(
      '..',
      '..',
      'bin',
      'cache',
      'flutter_tools.snapshot',
    ),
  );

  final File snapshotBackup =
      globals.fs.file('$flutterToolsSnapshotPath.bak');
  if (!snapshotBackup.existsSync()) {
    // No backup to restore.
    return;
  }

  snapshotBackup.renameSync(flutterToolsSnapshotPath);
}

Future<void> _createProject(Directory dir, List<String> createArgs) async {
  Cache.flutterRoot = '../..';
  final CreateCommand command = CreateCommand();
  final CommandRunner<void> runner = createTestCommandRunner(command);
  await runner.run(<String>[
    'create',
    ...createArgs,
    dir.path,
  ]);
}

typedef PubspecEditor = void Function(List<String> pubSpecContents);

Future<void> _editPubspecFile(
  Directory projectDir,
  PubspecEditor editor,
) async {
  final File pubspecYaml = projectDir.childFile('pubspec.yaml');
  expect(pubspecYaml, exists);

  final List<String> lines = await pubspecYaml.readAsLines();
  editor(lines);
  await pubspecYaml.writeAsString(lines.join('\n'));
}

Future<void> _replaceMainFile(Directory projectDir, String fileContents) async {
  final File mainFile = projectDir.childDirectory('lib').childFile('main.dart');
  await mainFile.writeAsString(fileContents);
}

PubspecEditor _addDependencyEditor(String packageToAdd, {String? version, String? path}) {
  assert(version != null || path != null,
      'Need to define a source for the package.');
  assert(version == null || path == null,
      'Cannot only load a package from path or from Pub, not both.');
  void editor(List<String> lines) {
    for (int i = 0; i < lines.length; i++) {
      final String line = lines[i];
      if (line.startsWith('dependencies:')) {
        lines.insert(
            i + 1,
            '  $packageToAdd: ${version ?? '\n'
                '   path: $path'}');
        break;
      }
    }
  }
  return editor;
}

PubspecEditor _setDartSDKVersionEditor(String version) {
  void editor(List<String> lines) {
    for (int i = 0; i < lines.length; i++) {
      final String line = lines[i];
      if (line.startsWith('environment:')) {
        for (i++; i < lines.length; i++) {
          final String innerLine = lines[i];
          final String sdkLine = "  sdk: '$version'";
          if(innerLine.isNotEmpty && !innerLine.startsWith('  ')) {
            lines.insert(i, sdkLine);
            break;
          }
          if(innerLine.startsWith('  sdk:')) {
            lines[i] = sdkLine;
            break;
          }
        }
        break;
      }
    }
  }
  return editor;
}

PubspecEditor _composeEditors(Iterable<PubspecEditor> editors) {
  void composedEditor(List<String> lines) {
    for (final PubspecEditor editor in editors) {
      editor(lines);
    }
  }
  return composedEditor;
}

Future<void> _addAnalysisOptions(
    Directory projectDir, List<String> linterRules) async {
  assert(linterRules.isNotEmpty);

  await projectDir.childFile('analysis_options.yaml').writeAsString('''
linter:
  rules:
${linterRules.map((String rule) => '    - $rule').join('\n')}
  ''');
}

Future<void> _analyzeEntity(FileSystemEntity target) async {
  final String flutterToolsSnapshotPath = globals.fs.path.absolute(
    globals.fs.path.join(
      '..',
      '..',
      'bin',
      'cache',
      'flutter_tools.snapshot',
    ),
  );

  final List<String> args = <String>[
    flutterToolsSnapshotPath,
    'analyze',
    target.path,
  ];

  final ProcessResult exec = await Process.run(
    globals.artifacts!.getHostArtifact(HostArtifact.engineDartBinary).path,
    args,
    workingDirectory: target is Directory ? target.path : target.dirname,
  );
  printOnFailure('Output of flutter analyze:');
  printOnFailure(exec.stdout.toString());
  printOnFailure(exec.stderr.toString());
  expect(exec.exitCode, 0);
}

Future<void> _buildWebProject(Directory workingDir) async {
  return _runFlutterSnapshot(<String>['build', 'web'], workingDir);
}

Future<void> _doFlutterPubGet(Directory workingDir) async {
  return _runFlutterSnapshot(<String>['pub', 'get'], workingDir);
}

// Runs a flutter command from a snapshot build.
// `flutterCommandArgs` are the arguments passed to flutter, like: ['build', 'web']
// to run `flutter build web`.
// `workingDir` is the directory on which the flutter command will be run.
Future<void> _runFlutterSnapshot(List<String> flutterCommandArgs, Directory workingDir) async {
  final String flutterToolsSnapshotPath = globals.fs.path.absolute(
    globals.fs.path.join(
      '..',
      '..',
      'bin',
      'cache',
      'flutter_tools.snapshot',
    ),
  );

  final List<String> args = <String>[
    flutterToolsSnapshotPath,
    ...flutterCommandArgs
  ];

  final ProcessResult exec = await Process.run(
    globals.artifacts!.getHostArtifact(HostArtifact.engineDartBinary).path,
    args,
    workingDirectory: workingDir.path,
  );
  printOnFailure('Output of flutter ${flutterCommandArgs.join(" ")}:');
  printOnFailure(exec.stdout.toString());
  printOnFailure(exec.stderr.toString());
  expect(exec.exitCode, 0);
}
