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

// @dart = 2.8

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() {
  Directory tempDir;
  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 to add a dependency with web support to trigger
    // the generated_plugin_registrant generation.
    await _addDependency(projectDir, 'shared_preferences',
        version: '^2.0.0');
    await _analyzeProject(projectDir);

    expect(
      projectDir.childFile('lib/generated_plugin_registrant.dart'),
      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',
    );
    await _analyzeProject(projectDir);

    expect(
      projectDir.childFile('lib/generated_plugin_registrant.dart'),
      exists,
    );
  }, 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(
    '.packages',
  ));

  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> _analyzeProject(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,
    'analyze',
  ];

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