// 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 _addDependency(projectDir, '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("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 _addDependency(projectDir, '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 _addDependency(
      projectDir,
      '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,
  ]);
}

Future<void> _addDependency(
  Directory projectDir,
  String package, {
  String? version,
  String? path,
}) async {
  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.');

  final File pubspecYaml = projectDir.childFile('pubspec.yaml');
  expect(pubspecYaml, exists);

  final List<String> lines = await pubspecYaml.readAsLines();
  for (int i = 0; i < lines.length; i++) {
    final String line = lines[i];
    if (line.startsWith('dependencies:')) {
      lines.insert(
          i + 1,
          '  $package: ${version ?? '\n'
              '    path: $path'}');
      break;
    }
  }
  await pubspecYaml.writeAsString(lines.join('\n'));
}

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);
}
