// 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:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/async_guard.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/compile.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:package_config/package_config.dart';

import '../src/common.dart';
import '../src/fake_process_manager.dart';
import '../src/fakes.dart';

void main() {
  late ResidentCompiler generator;
  late ResidentCompiler generatorWithScheme;
  late MemoryIOSink frontendServerStdIn;
  late BufferLogger testLogger;
  late StdoutHandler generatorStdoutHandler;
  late StdoutHandler generatorWithSchemeStdoutHandler;
  late FakeProcessManager fakeProcessManager;

  const List<String> frontendServerCommand = <String>[
    'HostArtifact.engineDartBinary',
    '--disable-dart-dev',
    'Artifact.frontendServerSnapshotForEngineDartSdk',
    '--sdk-root',
    'sdkroot/',
    '--incremental',
    '--target=flutter',
    '--experimental-emit-debug-metadata',
    '--output-dill',
    '/build/',
    '-Ddart.vm.profile=false',
    '-Ddart.vm.product=false',
    '--enable-asserts',
    '--track-widget-creation',
  ];

  setUp(() {
    testLogger = BufferLogger.test();
    frontendServerStdIn = MemoryIOSink();

    fakeProcessManager = FakeProcessManager.empty();
    generatorStdoutHandler = StdoutHandler(logger: testLogger, fileSystem: MemoryFileSystem.test());
    generatorWithSchemeStdoutHandler = StdoutHandler(logger: testLogger, fileSystem: MemoryFileSystem.test());
    generator = DefaultResidentCompiler(
      'sdkroot',
      buildMode: BuildMode.debug,
      logger: testLogger,
      processManager: fakeProcessManager,
      artifacts: Artifacts.test(),
      platform: FakePlatform(),
      fileSystem: MemoryFileSystem.test(),
      stdoutHandler: generatorStdoutHandler,
    );
    generatorWithScheme = DefaultResidentCompiler(
      'sdkroot',
      buildMode: BuildMode.debug,
      logger: testLogger,
      processManager: fakeProcessManager,
      artifacts: Artifacts.test(),
      platform: FakePlatform(),
      fileSystemRoots: <String>[
        '/foo/bar/fizz',
      ],
      fileSystemScheme: 'scheme',
      fileSystem: MemoryFileSystem.test(),
      stdoutHandler: generatorWithSchemeStdoutHandler,
    );
  });

  testWithoutContext('incremental compile single dart compile', () async {
    fakeProcessManager.addCommand(FakeCommand(
      command: const <String>[...frontendServerCommand, '--verbosity=error'],
      stdout: 'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0',
      stdin: frontendServerStdIn,
    ));

    final CompilerOutput? output = await generator.recompile(
      Uri.parse('/path/to/main.dart'),
        null /* invalidatedFiles */,
      outputPath: '/build/',
      packageConfig: PackageConfig.empty,
      fs: MemoryFileSystem(),
      projectRootPath: '',
    );
    expect(frontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');
    expect(testLogger.errorText, equals('line1\nline2\n'));
    expect(output?.outputFilename, equals('/path/to/main.dart.dill'));
    expect(fakeProcessManager, hasNoRemainingExpectations);
  });

  testWithoutContext('incremental compile single dart compile with filesystem scheme', () async {
    fakeProcessManager.addCommand(FakeCommand(
      command: const <String>[
        ...frontendServerCommand,
        '--filesystem-root',
        '/foo/bar/fizz',
        '--filesystem-scheme',
        'scheme',
        '--verbosity=error',
      ],
      stdout: 'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0',
      stdin: frontendServerStdIn,
    ));

    final CompilerOutput? output = await generatorWithScheme.recompile(
      Uri.parse('file:///foo/bar/fizz/main.dart'),
        null /* invalidatedFiles */,
      outputPath: '/build/',
      packageConfig: PackageConfig.empty,
      fs: MemoryFileSystem(),
      projectRootPath: '',
    );
    expect(frontendServerStdIn.getAndClear(), 'compile scheme:///main.dart\n');
    expect(testLogger.errorText, equals('line1\nline2\n'));
    expect(output?.outputFilename, equals('/path/to/main.dart.dill'));
    expect(fakeProcessManager, hasNoRemainingExpectations);
  });

  testWithoutContext('incremental compile single dart compile abnormally terminates', () async {
    fakeProcessManager.addCommand(FakeCommand(
      command: const <String>[...frontendServerCommand, '--verbosity=error'],
      stdin: frontendServerStdIn,
    ));

    expect(asyncGuard(() => generator.recompile(
      Uri.parse('/path/to/main.dart'),
      null, /* invalidatedFiles */
      outputPath: '/build/',
      packageConfig: PackageConfig.empty,
      fs: MemoryFileSystem(),
      projectRootPath: '',
    )), throwsToolExit());
  });

  testWithoutContext('incremental compile single dart compile abnormally terminates via exitCode', () async {
    fakeProcessManager.addCommand(FakeCommand(
      command: const <String>[...frontendServerCommand, '--verbosity=error'],
      stdin: frontendServerStdIn,
      exitCode: 1,
    ));

    expect(asyncGuard(() => generator.recompile(
      Uri.parse('/path/to/main.dart'),
      null, /* invalidatedFiles */
      outputPath: '/build/',
      packageConfig: PackageConfig.empty,
      fs: MemoryFileSystem(),
      projectRootPath: '',
    )), throwsToolExit(message: 'the Dart compiler exited unexpectedly.'));
  });

  testWithoutContext('incremental compile and recompile', () async {
    final Completer<void> completer = Completer<void>();
    fakeProcessManager.addCommand(FakeCommand(
      command: const <String>[...frontendServerCommand, '--verbosity=error'],
      stdout: 'result abc\nline0\nline1\nabc\nabc /path/to/main.dart.dill 0',
      stdin: frontendServerStdIn,
      completer: completer,
    ));

    await generator.recompile(
      Uri.parse('/path/to/main.dart'),
      null, /* invalidatedFiles */
      outputPath: '/build/',
      packageConfig: PackageConfig.empty,
      projectRootPath: '',
      fs: MemoryFileSystem(),
    );
    expect(frontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');

    // No accept or reject commands should be issued until we
    // send recompile request.
    await _accept(generator, frontendServerStdIn, '');
    await _reject(generatorStdoutHandler, generator, frontendServerStdIn, '', '');

    await _recompile(generatorStdoutHandler, generator, frontendServerStdIn,
      'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0\n');

    await _accept(generator, frontendServerStdIn, r'^accept\n$');

    await _recompile(generatorStdoutHandler, generator, frontendServerStdIn,
      'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0\n');
    // No sources returned from reject command.
    await _reject(generatorStdoutHandler, generator, frontendServerStdIn, 'result abc\nabc\n',
      r'^reject\n$');
    completer.complete();
    expect(frontendServerStdIn.getAndClear(), isEmpty);
    expect(testLogger.errorText, equals(
      'line0\nline1\n'
      'line1\nline2\n'
      'line1\nline2\n'
    ));
  });

  testWithoutContext('incremental compile and recompile with filesystem scheme', () async {
    final Completer<void> completer = Completer<void>();
    fakeProcessManager.addCommand(FakeCommand(
      command: const <String>[
        ...frontendServerCommand,
        '--filesystem-root',
        '/foo/bar/fizz',
        '--filesystem-scheme',
        'scheme',
        '--verbosity=error',
      ],
      stdout: 'result abc\nline0\nline1\nabc\nabc /path/to/main.dart.dill 0',
      stdin: frontendServerStdIn,
      completer: completer,
    ));
    await generatorWithScheme.recompile(
      Uri.parse('file:///foo/bar/fizz/main.dart'),
      null, /* invalidatedFiles */
      outputPath: '/build/',
      packageConfig: PackageConfig.empty,
      fs: MemoryFileSystem(),
      projectRootPath: '',
    );
    expect(frontendServerStdIn.getAndClear(), 'compile scheme:///main.dart\n');

    // No accept or reject commands should be issued until we
    // send recompile request.
    await _accept(generatorWithScheme, frontendServerStdIn, '');
    await _reject(generatorWithSchemeStdoutHandler, generatorWithScheme, frontendServerStdIn, '', '');

    await _recompile(generatorWithSchemeStdoutHandler, generatorWithScheme, frontendServerStdIn,
      'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0\n',
      mainUri: Uri.parse('file:///foo/bar/fizz/main.dart'),
      expectedMainUri: 'scheme:///main.dart');

    await _accept(generatorWithScheme, frontendServerStdIn, r'^accept\n$');

    await _recompile(generatorWithSchemeStdoutHandler, generatorWithScheme, frontendServerStdIn,
      'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0\n',
      mainUri: Uri.parse('file:///foo/bar/fizz/main.dart'),
      expectedMainUri: 'scheme:///main.dart');
    // No sources returned from reject command.
    await _reject(generatorWithSchemeStdoutHandler, generatorWithScheme, frontendServerStdIn, 'result abc\nabc\n',
      r'^reject\n$');
    completer.complete();
    expect(frontendServerStdIn.getAndClear(), isEmpty);
    expect(testLogger.errorText, equals(
      'line0\nline1\n'
      'line1\nline2\n'
      'line1\nline2\n'
    ));
  });

  testWithoutContext('incremental compile and recompile non-entrypoint file with filesystem scheme', () async {
    final Uri mainUri = Uri.parse('file:///foo/bar/fizz/main.dart');
    const String expectedMainUri = 'scheme:///main.dart';
    final List<Uri> updatedUris = <Uri>[
      mainUri,
      Uri.parse('file:///foo/bar/fizz/other.dart'),
    ];
    const List<String> expectedUpdatedUris = <String>[
      expectedMainUri,
      'scheme:///other.dart',
    ];

    final Completer<void> completer = Completer<void>();
    fakeProcessManager.addCommand(FakeCommand(
      command: const <String>[
        ...frontendServerCommand,
        '--filesystem-root',
        '/foo/bar/fizz',
        '--filesystem-scheme',
        'scheme',
        '--verbosity=error',
      ],
      stdout: 'result abc\nline0\nline1\nabc\nabc /path/to/main.dart.dill 0',
      stdin: frontendServerStdIn,
      completer: completer,
    ));
    await generatorWithScheme.recompile(
      Uri.parse('file:///foo/bar/fizz/main.dart'),
      null, /* invalidatedFiles */
      outputPath: '/build/',
      packageConfig: PackageConfig.empty,
      fs: MemoryFileSystem(),
      projectRootPath: '',
    );
    expect(frontendServerStdIn.getAndClear(), 'compile scheme:///main.dart\n');

    // No accept or reject commands should be issued until we
    // send recompile request.
    await _accept(generatorWithScheme, frontendServerStdIn, '');
    await _reject(generatorWithSchemeStdoutHandler, generatorWithScheme, frontendServerStdIn, '', '');

    await _recompile(generatorWithSchemeStdoutHandler, generatorWithScheme, frontendServerStdIn,
      'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0\n',
      mainUri: mainUri,
      expectedMainUri: expectedMainUri,
      updatedUris: updatedUris,
      expectedUpdatedUris: expectedUpdatedUris);

    await _accept(generatorWithScheme, frontendServerStdIn, r'^accept\n$');

    await _recompile(generatorWithSchemeStdoutHandler, generatorWithScheme, frontendServerStdIn,
      'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0\n',
      mainUri: mainUri,
      expectedMainUri: expectedMainUri,
      updatedUris: updatedUris,
      expectedUpdatedUris: expectedUpdatedUris);
    // No sources returned from reject command.
    await _reject(generatorWithSchemeStdoutHandler, generatorWithScheme, frontendServerStdIn, 'result abc\nabc\n',
      r'^reject\n$');
    completer.complete();
    expect(frontendServerStdIn.getAndClear(), isEmpty);
    expect(testLogger.errorText, equals(
      'line0\nline1\n'
      'line1\nline2\n'
      'line1\nline2\n'
    ));
  });

  testWithoutContext('incremental compile can suppress errors', () async {
    final Completer<void> completer = Completer<void>();
    fakeProcessManager.addCommand(FakeCommand(
      command: const <String>[...frontendServerCommand, '--verbosity=error'],
      stdout: 'result abc\nline0\nline1\nabc\nabc /path/to/main.dart.dill 0',
      stdin: frontendServerStdIn,
      completer: completer,
    ));

    await generator.recompile(
      Uri.parse('/path/to/main.dart'),
      <Uri>[],
      outputPath: '/build/',
      packageConfig: PackageConfig.empty,
      fs: MemoryFileSystem(),
      projectRootPath: '',
    );
    expect(frontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');

    await _recompile(generatorStdoutHandler, generator, frontendServerStdIn,
      'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0\n');

    await _accept(generator, frontendServerStdIn, r'^accept\n$');

    await _recompile(generatorStdoutHandler, generator, frontendServerStdIn,
      'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0\n', suppressErrors: true);

    completer.complete();
    expect(frontendServerStdIn.getAndClear(), isEmpty);

    // Compiler message is not printed with suppressErrors: true above.
    expect(testLogger.errorText, isNot(equals(
      'line1\nline2\n'
    )));
    expect(testLogger.traceText, contains(
      'line1\nline2\n'
    ));
  });

  testWithoutContext('incremental compile and recompile twice', () async {
    final Completer<void> completer = Completer<void>();
    fakeProcessManager.addCommand(FakeCommand(
      command: const <String>[...frontendServerCommand, '--verbosity=error'],
      stdout: 'result abc\nline0\nline1\nabc\nabc /path/to/main.dart.dill 0',
      stdin: frontendServerStdIn,
      completer: completer,
    ));
    await generator.recompile(
      Uri.parse('/path/to/main.dart'),
      null /* invalidatedFiles */,
      outputPath: '/build/',
      packageConfig: PackageConfig.empty,
      fs: MemoryFileSystem(),
      projectRootPath: '',
    );
    expect(frontendServerStdIn.getAndClear(), 'compile /path/to/main.dart\n');

    await _recompile(generatorStdoutHandler, generator, frontendServerStdIn,
      'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0\n');
    await _recompile(generatorStdoutHandler, generator, frontendServerStdIn,
      'result abc\nline2\nline3\nabc\nabc /path/to/main.dart.dill 0\n');

    completer.complete();
    expect(frontendServerStdIn.getAndClear(), isEmpty);
    expect(testLogger.errorText, equals(
      'line0\nline1\n'
      'line1\nline2\n'
      'line2\nline3\n'
    ));
  });

  testWithoutContext('incremental compile with dartPluginRegistrant', () async {
    fakeProcessManager.addCommand(FakeCommand(
      command: const <String>[
        ...frontendServerCommand,
        '--filesystem-root',
        '/foo/bar/fizz',
        '--filesystem-scheme',
        'scheme',
        '--source',
        'some/dir/plugin_registrant.dart',
        '--source',
        'package:flutter/src/dart_plugin_registrant.dart',
        '-Dflutter.dart_plugin_registrant=some/dir/plugin_registrant.dart',
        '--verbosity=error',
      ],
      stdout: 'result abc\nline1\nline2\nabc\nabc /path/to/main.dart.dill 0',
      stdin: frontendServerStdIn,
    ));

    final MemoryFileSystem fs = MemoryFileSystem();
    final File dartPluginRegistrant = fs.file('some/dir/plugin_registrant.dart')..createSync(recursive: true);
    final CompilerOutput? output = await generatorWithScheme.recompile(
      Uri.parse('file:///foo/bar/fizz/main.dart'),
        null /* invalidatedFiles */,
      outputPath: '/build/',
      packageConfig: PackageConfig.empty,
      fs: fs,
      projectRootPath: '',
      checkDartPluginRegistry: true,
      dartPluginRegistrant: dartPluginRegistrant,
    );
    expect(frontendServerStdIn.getAndClear(), 'compile scheme:///main.dart\n');
    expect(testLogger.errorText, equals('line1\nline2\n'));
    expect(output?.outputFilename, equals('/path/to/main.dart.dill'));
    expect(fakeProcessManager, hasNoRemainingExpectations);
  });
}

Future<void> _recompile(
  StdoutHandler stdoutHandler,
  ResidentCompiler generator,
  MemoryIOSink frontendServerStdIn,
  String mockCompilerOutput, {
  bool suppressErrors = false,
  Uri? mainUri,
  String expectedMainUri = '/path/to/main.dart',
  List<Uri>? updatedUris,
  List<String>? expectedUpdatedUris,
}) async {
  mainUri ??= Uri.parse('/path/to/main.dart');
  updatedUris ??= <Uri>[mainUri];
  expectedUpdatedUris ??= <String>[expectedMainUri];

  final Future<CompilerOutput?> recompileFuture = generator.recompile(
    mainUri,
    updatedUris,
    outputPath: '/build/',
    packageConfig: PackageConfig.empty,
    suppressErrors: suppressErrors,
    fs: MemoryFileSystem(),
    projectRootPath: '',
  );

  // Put content into the output stream after generator.recompile gets
  // going few lines below, resets completer.
  scheduleMicrotask(() {
    LineSplitter.split(mockCompilerOutput).forEach(stdoutHandler.handler);
  });
  final CompilerOutput? output = await recompileFuture;
  expect(output?.outputFilename, equals('/path/to/main.dart.dill'));
  final String commands = frontendServerStdIn.getAndClear();
  final RegExp whitespace = RegExp(r'\s+');
  final List<String> parts = commands.split(whitespace);

  // Test that uuid matches at beginning and end.
  expect(parts[2], equals(parts[3 + updatedUris.length]));
  expect(parts[1], equals(expectedMainUri));
  for (int i = 0; i < expectedUpdatedUris.length; i++) {
    expect(parts[3 + i], equals(expectedUpdatedUris[i]));
  }
}

Future<void> _accept(
  ResidentCompiler generator,
  MemoryIOSink frontendServerStdIn,
  String expected,
) async {
  generator.accept();
  final String commands = frontendServerStdIn.getAndClear();
  final RegExp re = RegExp(expected);
  expect(commands, matches(re));
}

Future<void> _reject(
  StdoutHandler stdoutHandler,
  ResidentCompiler generator,
  MemoryIOSink frontendServerStdIn,
  String mockCompilerOutput,
  String expected,
) async {
  // Put content into the output stream after generator.recompile gets
  // going few lines below, resets completer.
  final Future<CompilerOutput?> rejectFuture = generator.reject();
  scheduleMicrotask(() {
    LineSplitter.split(mockCompilerOutput).forEach(stdoutHandler.handler);
  });
  final CompilerOutput? output = await rejectFuture;
  expect(output, isNull);

  final String commands = frontendServerStdIn.getAndClear();
  final RegExp re = RegExp(expected);
  expect(commands, matches(re));
}
