// 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:ffi' as ffi show Abi;
import 'dart:io' as io;

import 'package:engine_repo_tools/engine_repo_tools.dart';
import 'package:engine_tool/src/environment.dart';
import 'package:engine_tool/src/logger.dart';
import 'package:path/path.dart' as path;
import 'package:platform/platform.dart';
import 'package:process_fakes/process_fakes.dart';
import 'package:process_runner/process_runner.dart';
import 'package:test/test.dart';

/// Each CannedProcess has a command matcher and the result of an executed
/// process. The matcher is used to determine when to use a registered
/// CannedProcess.
class CannedProcess {
  CannedProcess(
    this.commandMatcher, {
    int exitCode = 0,
    String stdout = '',
    String stderr = '',
  })  : _exitCode = exitCode,
        _stdout = stdout,
        _stderr = stderr;

  final bool Function(List<String> command) commandMatcher;
  final int _exitCode;
  final String _stdout;
  final String _stderr;

  FakeProcess get fakeProcess {
    return FakeProcess(exitCode: _exitCode, stdout: _stdout, stderr: _stderr);
  }

  io.ProcessResult get processResult {
    return io.ProcessResult(0, _exitCode, _stdout, _stderr);
  }
}

/// ExecutedProcess includes the command and the result.
class ExecutedProcess {
  ExecutedProcess(this.command, this.result, this.exitCode);
  final List<String> command;
  final FakeProcess result;
  final int exitCode;

  @override
  String toString() {
    return '${command.join(' ')} exitCode=$exitCode';
  }
}

/// TestEnvironment includes an Environment with some test-specific extras.
class TestEnvironment {
  TestEnvironment(
    Engine engine, {
    Logger? logger,
    ffi.Abi abi = ffi.Abi.macosArm64,
    bool verbose = false,
    DateTime Function() now = DateTime.now,
    this.cannedProcesses = const <CannedProcess>[],
  }) {
    testLogs = <LogRecord>[];
    logger ??= Logger.test(testLogs.add);
    environment = Environment(
      abi: abi,
      engine: engine,
      platform: FakePlatform(
        operatingSystem: _operatingSystemForAbi(abi),
        resolvedExecutable: io.Platform.resolvedExecutable,
        pathSeparator: _pathSeparatorForAbi(abi),
        numberOfProcessors: 32,
      ),
      processRunner: ProcessRunner(
          processManager: FakeProcessManager(onStart: (List<String> command) {
        final FakeProcess processResult =
            _getCannedResult(command, cannedProcesses);
        processResult.exitCode.then((int exitCode) {
          processHistory.add(ExecutedProcess(command, processResult, exitCode));
        });
        return processResult;
      }, onRun: (List<String> command) {
        final io.ProcessResult result = _getCannedProcessResult(
          command,
          cannedProcesses,
        );
        processHistory.add(ExecutedProcess(
          command,
          FakeProcess(
            exitCode: result.exitCode,
            stdout: result.stdout as String,
            stderr: result.stderr as String,
          ),
          result.exitCode,
        ));
        return result;
      })),
      logger: logger,
      verbose: verbose,
      now: now,
    );
  }

  factory TestEnvironment.withTestEngine({
    bool withRbe = false,
    ffi.Abi abi = ffi.Abi.linuxX64,
    List<CannedProcess> cannedProcesses = const <CannedProcess>[],
    bool verbose = false,
    DateTime Function() now = DateTime.now,
  }) {
    final io.Directory rootDir = io.Directory.systemTemp.createTempSync('et');
    final TestEngine engine = TestEngine.createTemp(rootDir: rootDir);
    if (withRbe) {
      io.Directory(path.join(
        engine.srcDir.path,
        'flutter',
        'build',
        'rbe',
      )).createSync(recursive: true);
    }
    // When GN runs, always try to create out/host_debug.
    final CannedProcess cannedGn = CannedProcess((List<String> command) {
      if (command[0].endsWith('/gn') && !command.contains('desc')) {
        io.Directory(path.join(
          engine.outDir.path,
          'host_debug',
        )).createSync(recursive: true);
        return true;
      }
      return false;
    });
    final TestEnvironment testEnvironment = TestEnvironment(
      engine,
      abi: abi,
      cannedProcesses: cannedProcesses + <CannedProcess>[cannedGn],
      verbose: verbose,
      now: now,
    );
    return testEnvironment;
  }

  void cleanup() {
    try {
      if (environment.engine is TestEngine) {
        environment.engine.srcDir.parent.deleteSync(recursive: true);
      }
    } catch (_) {
      // Ignore failure to clean up.
    }
  }

  /// Environment.
  late final Environment environment;

  /// List of CannedProcesses that are registered in this environment.
  final List<CannedProcess> cannedProcesses;

  /// A history of all executed processes.
  final List<ExecutedProcess> processHistory = <ExecutedProcess>[];

  /// Test log output.
  late final List<LogRecord> testLogs;
}

String _operatingSystemForAbi(ffi.Abi abi) {
  switch (abi) {
    case ffi.Abi.linuxArm:
    case ffi.Abi.linuxArm64:
    case ffi.Abi.linuxIA32:
    case ffi.Abi.linuxX64:
    case ffi.Abi.linuxRiscv32:
    case ffi.Abi.linuxRiscv64:
      return Platform.linux;
    case ffi.Abi.macosArm64:
    case ffi.Abi.macosX64:
      return Platform.macOS;
    default:
      throw UnimplementedError('Unhandled abi=$abi');
  }
}

String _pathSeparatorForAbi(ffi.Abi abi) {
  switch (abi) {
    case ffi.Abi.windowsArm64:
    case ffi.Abi.windowsIA32:
    case ffi.Abi.windowsX64:
      return r'\';
    default:
      return '/';
  }
}

FakeProcess _getCannedResult(
    List<String> command, List<CannedProcess> cannedProcesses) {
  for (final CannedProcess cp in cannedProcesses) {
    final bool matched = cp.commandMatcher(command);
    if (matched) {
      return cp.fakeProcess;
    }
  }
  return FakeProcess();
}

io.ProcessResult _getCannedProcessResult(
    List<String> command, List<CannedProcess> cannedProcesses) {
  for (final CannedProcess cp in cannedProcesses) {
    final bool matched = cp.commandMatcher(command);
    if (matched) {
      return cp.processResult;
    }
  }
  return io.ProcessResult(0, 0, '', '');
}

Matcher containsCommand(bool Function(List<String> command) matcher) {
  return predicate((List<ExecutedProcess> history) {
    return history.any((ExecutedProcess process) {
      return matcher(process.command);
    });
  }, 'contains command');
}

Matcher doesNotContainCommand(bool Function(List<String> command) matcher) {
  return predicate((List<ExecutedProcess> history) {
    return !history.any((ExecutedProcess process) {
      return matcher(process.command);
    });
  }, 'does not contain command');
}
