// Copyright 2013 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 'dart:convert' show LineSplitter, utf8;
import 'dart:io' as io;

import 'package:args/command_runner.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;

import 'environment.dart';
import 'exceptions.dart';
import 'felt_config.dart';

enum RuntimeMode {
  debug,
  profile,
  release,
}

class FilePath {
  FilePath.fromCwd(String relativePath)
      : _absolutePath = path.absolute(relativePath);
  FilePath.fromWebUi(String relativePath)
      : _absolutePath = path.join(environment.webUiRootDir.path, relativePath);
  FilePath.fromTestSet(TestSet testSet, String relativePath)
      : _absolutePath = path.join(getTestSetDirectory(testSet).path, relativePath);

  final String _absolutePath;

  String get absolute => _absolutePath;
  String get relativeToCwd => path.relative(_absolutePath);
  String get relativeToWebUi =>
      path.relative(_absolutePath, from: environment.webUiRootDir.path);

  @override
  bool operator ==(Object other) {
    return other is FilePath && other._absolutePath == _absolutePath;
  }

  @override
  int get hashCode => _absolutePath.hashCode;

  @override
  String toString() => _absolutePath;
}

/// Runs [executable] merging its output into the current process' standard out and standard error.
Future<int> runProcess(
  String executable,
  List<String> arguments, {
  String? workingDirectory,
  bool failureIsSuccess = false,
  Map<String, String> environment = const <String, String>{},
}) async {
  final ProcessManager manager = await startProcess(
    executable,
    arguments,
    workingDirectory: workingDirectory,
    failureIsSuccess: failureIsSuccess,
    environment: environment,
  );
  return manager.wait();
}

/// Runs the process and returns its standard output as a string.
///
/// Standard error output is ignored (use [ProcessManager.evalStderr] for that).
///
/// Throws an exception if the process exited with a non-zero exit code.
Future<String> evalProcess(
  String executable,
  List<String> arguments, {
  String? workingDirectory,
  Map<String, String> environment = const <String, String>{},
}) async {
  final ProcessManager manager = await startProcess(
    executable,
    arguments,
    workingDirectory: workingDirectory,
    environment: environment,
    evalOutput: true,
  );
  return manager.evalStdout();
}

/// Starts a process using the [executable], passing it [arguments].
///
/// Returns a process manager that decorates the process with extra
/// functionality. See [ProcessManager] for what it can do.
///
/// If [workingDirectory] is not null makes it the current working directory of
/// the process. Otherwise, the process inherits this processes working
/// directory.
///
/// If [failureIsSuccess] is set to true, the returned [ProcessManager] treats
/// non-zero exit codes as success, and zero exit code as failure.
///
/// If [evalOutput] is set to true, collects and decodes the process' standard
/// streams into in-memory strings.
Future<ProcessManager> startProcess(
  String executable,
  List<String> arguments, {
  String? workingDirectory,
  bool failureIsSuccess = false,
  bool evalOutput = false,
  Map<String, String> environment = const <String, String>{},
}) async {
  final io.Process process = await io.Process.start(
    executable,
    arguments,
    workingDirectory: workingDirectory,
    // Running the process in a system shell for Windows. Otherwise
    // the process is not able to get Dart from path.
    runInShell: io.Platform.isWindows,
    // When [evalOutput] is false, we don't need to intercept the stdout of the
    // sub-process. In this case, it's better to run the sub-process in the
    // `inheritStdio` mode which lets it print directly to the terminal.
    // This allows sub-processes such as `ninja` to use all kinds of terminal
    // features like printing colors, printing progress on the same line, etc.
    mode: evalOutput ? io.ProcessStartMode.normal : io.ProcessStartMode.inheritStdio,
    environment: environment,
  );
  processesToCleanUp.add(process);

  return ProcessManager._(
    executable: executable,
    arguments: arguments,
    workingDirectory: workingDirectory,
    process: process,
    evalOutput: evalOutput,
    failureIsSuccess: failureIsSuccess,
  );
}

/// Manages a process running outside `felt`.
class ProcessManager {
  /// Creates a process manager that manages [process].
  ProcessManager._({
    required this.executable,
    required this.arguments,
    required this.workingDirectory,
    required this.process,
    required bool evalOutput,
    required bool failureIsSuccess,
  }) : _evalOutput = evalOutput, _failureIsSuccess = failureIsSuccess {
    if (_evalOutput) {
      _forwardStream(process.stdout, _stdout);
      _forwardStream(process.stderr, _stderr);
    }
  }

  /// The executable, from which the process was spawned.
  final String executable;

  /// The arguments passed to the prcess.
  final List<String> arguments;

  /// The current working directory (CWD) of the child process.
  ///
  /// If null, the child process inherits `felt`'s CWD.
  final String? workingDirectory;

  /// The process being managed by this manager.
  final io.Process process;

  /// Whether the standard output and standard error should be decoded into
  /// strings while running the process.
  final bool _evalOutput;

  /// Whether non-zero exit code is considered successful completion of the
  /// process.
  ///
  /// See also [wait].
  final bool _failureIsSuccess;

  final StringBuffer _stdout = StringBuffer();
  final StringBuffer _stderr = StringBuffer();

  void _forwardStream(Stream<List<int>> stream, StringSink buffer) {
    stream
      .transform(utf8.decoder)
      .transform(const LineSplitter())
      .listen(buffer.writeln);
  }

  /// Waits for the [process] to exit. Returns the exit code.
  ///
  /// The returned future completes successfully if:
  ///
  ///  * [failureIsSuccess] is false and the process exited with exit code 0.
  ///  * [failureIsSuccess] is true and the process exited with a non-zero exit code.
  ///
  /// In all other cicumstances the future completes with an error.
  Future<int> wait() async {
    final int exitCode = await process.exitCode;
    if (!_failureIsSuccess && exitCode != 0) {
      _throwProcessException(
        description: 'Sub-process failed.',
        exitCode: exitCode,
      );
    }
    return exitCode;
  }

  /// If [evalOutput] is true, wait for the process to finish then returns the
  /// decoded standard streams.
  Future<ProcessOutput> eval() async {
    if (!_evalOutput) {
      kill();
      _throwProcessException(
        description: 'Cannot eval process output. The process was launched '
            'with `evalOutput` set to false.',
      );
    }
    final int exitCode = await wait();
    return ProcessOutput(
      exitCode: exitCode,
      stdout: _stdout.toString(),
      stderr: _stderr.toString(),
    );
  }

  /// A convenience method on top of [eval] that only extracts standard output.
  Future<String> evalStdout() async {
    return (await eval()).stdout;
  }

  /// A convenience method on top of [eval] that only extracts standard error.
  Future<String> evalStderr() async {
    return (await eval()).stderr;
  }

  Never _throwProcessException({required String description, int? exitCode}) {
    throw ProcessException(
      description: description,
      executable: executable,
      arguments: arguments,
      workingDirectory: workingDirectory,
      exitCode: exitCode,
    );
  }

  /// Kills the [process] by sending it the [signal].
  bool kill([io.ProcessSignal signal = io.ProcessSignal.sigterm]) {
    return process.kill(signal);
  }
}

/// Stringified standard output and standard error streams from a process.
class ProcessOutput {
  ProcessOutput({
    required this.exitCode,
    required this.stdout,
    required this.stderr,
  });

  /// The exit code of the process.
  final int exitCode;

  /// Standard output of the process decoded as a string.
  final String stdout;

  /// Standard error of the process decoded as a string.
  final String stderr;
}

Future<void> runFlutter(
  String workingDirectory,
  List<String> arguments, {
  bool useSystemFlutter = false,
}) async {
  final String executable =
      useSystemFlutter ? 'flutter' : environment.flutterCommand.path;
  arguments.add('--local-engine=host_debug_unopt');
  final int exitCode = await runProcess(
    executable,
    arguments,
    workingDirectory: workingDirectory,
  );

  if (exitCode != 0) {
    throw ToolExit(
      'ERROR: Failed to run $executable with '
      'arguments $arguments. Exited with exit code $exitCode',
      exitCode: exitCode,
    );
  }
}

/// An exception related to an attempt to spawn a sub-process.
@immutable
class ProcessException implements Exception {
  const ProcessException({
    required this.description,
    required this.executable,
    required this.arguments,
    required this.workingDirectory,
    this.exitCode,
  });

  final String description;
  final String executable;
  final List<String> arguments;
  final String? workingDirectory;

  /// The exit code of the process.
  ///
  /// The value is null if the exception is thrown before the process exits.
  /// For example, this can happen on invalid attempts to start a process, or
  /// when a process is stuck and is unable to exit.
  final int? exitCode;

  @override
  String toString() {
    final StringBuffer message = StringBuffer();
    message
      ..writeln(description)
      ..writeln('Command: $executable ${arguments.join(' ')}')
      ..writeln('Working directory: ${workingDirectory ?? io.Directory.current.path}');
    if (exitCode != null) {
      message.writeln('Exit code: $exitCode');
    }
    return '$message';
  }
}

/// Adds utility methods
mixin ArgUtils<T> on Command<T> {
  /// Extracts a boolean argument from [argResults].
  bool boolArg(String name) => argResults![name] as bool;

  /// Extracts a string argument from [argResults].
  String stringArg(String name) => argResults![name] as String;

  RuntimeMode get runtimeMode {
    final bool isProfile = boolArg('profile');
    final bool isDebug = boolArg('debug');
    if (isProfile && isDebug) {
      throw ToolExit('Cannot specify both --profile and --debug at the same time.');
    }
    if (isProfile) {
      return RuntimeMode.profile;
    } else if (isDebug) {
      return RuntimeMode.debug;
    } else {
      return RuntimeMode.release;
    }
  }
}

io.Directory getBuildDirectoryForRuntimeMode(RuntimeMode runtimeMode) =>
  switch (runtimeMode) {
    RuntimeMode.debug => environment.wasmDebugUnoptOutDir,
    RuntimeMode.profile => environment.wasmProfileOutDir,
    RuntimeMode.release => environment.wasmReleaseOutDir,
  };

/// There might be proccesses started during the tests.
///
/// Use this list to store those Processes, for cleaning up before shutdown.
final List<io.Process> processesToCleanUp = <io.Process>[];

/// There might be temporary directories created during the tests.
///
/// Use this list to store those directories and for deleteing them before
/// shutdown.
final List<io.Directory> temporaryDirectories = <io.Directory>[];

typedef AsyncCallback = Future<void> Function();

/// There might be additional cleanup needs to be done after the tools ran.
///
/// Add these operations here to make sure that they will run before felt
/// exit.
final List<AsyncCallback> cleanupCallbacks = <AsyncCallback>[];

/// Cleanup the remaning processes, close open browsers, delete temp files.
Future<void> cleanup() async {
  // Cleanup remaining processes if any.
  if (processesToCleanUp.isNotEmpty) {
    for (final io.Process process in processesToCleanUp) {
      process.kill();
    }
  }
  // Delete temporary directories.
  if (temporaryDirectories.isNotEmpty) {
    for (final io.Directory directory in temporaryDirectories) {
      if (!directory.existsSync()) {
        directory.deleteSync(recursive: true);
      }
    }
  }

  for (final AsyncCallback callback in cleanupCallbacks) {
    await callback();
  }
}

io.Directory getTestSetDirectory(TestSet testSet) {
  return io.Directory(
    path.join(
      environment.webUiTestDir.path,
      testSet.directory,
    )
  );
}

io.Directory getBundleBuildDirectory(TestBundle bundle) {
  return io.Directory(
    path.join(
      environment.webUiBuildDir.path,
      'test_bundles',
      bundle.name,
    )
  );
}

io.Directory getSkiaGoldDirectoryForSuite(TestSuite suite) {
  return io.Directory(
    path.join(
      environment.webUiSkiaGoldDirectory.path,
      suite.name,
    )
  );
}

extension AnsiColors on String {
  static bool shouldEscape = io.stdout.hasTerminal && io.stdout.supportsAnsiEscapes;

  static const String _noColorCode = '\u001b[39m';

  String _wrapText(String prefix, String suffix) => shouldEscape
    ? '$prefix$this$suffix' : this;

  String _colorText(String colorCode) => _wrapText(colorCode, _noColorCode);

  String get ansiBlack => _colorText('\u001b[30m');
  String get ansiRed => _colorText('\u001b[31m');
  String get ansiGreen => _colorText('\u001b[32m');
  String get ansiYellow => _colorText('\u001b[33m');
  String get ansiBlue => _colorText('\u001b[34m');
  String get ansiMagenta => _colorText('\u001b[35m');
  String get ansiCyan => _colorText('\u001b[36m');
  String get ansiWhite => _colorText('\u001b[37m');

  String get ansiBold => _wrapText('\u001b[1m', '\u001b[0m');
}
