// 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:engine_tool/src/proc_utils.dart';
import 'package:engine_tool/src/worker_pool.dart';
import 'package:litetest/litetest.dart';
import 'package:platform/platform.dart';
import 'package:process_fakes/process_fakes.dart';
import 'package:process_runner/process_runner.dart';

void main() {
  final Engine engine;
  try {
    engine = Engine.findWithin();
  } catch (e) {
    io.stderr.writeln(e);
    io.exitCode = 1;
    return;
  }

  (Environment, List<List<String>>) macEnv(Logger logger) {
    final List<List<String>> runHistory = <List<String>>[];
    return (
      Environment(
        abi: ffi.Abi.macosArm64,
        engine: engine,
        platform: FakePlatform(
            operatingSystem: Platform.macOS,
            resolvedExecutable: io.Platform.resolvedExecutable,
            pathSeparator: '/'),
        processRunner: ProcessRunner(
            processManager: FakeProcessManager(onStart: (List<String> command) {
          runHistory.add(command);
          switch (command) {
            case ['success']:
              return FakeProcess(stdout: 'stdout success');
            case ['failure']:
              return FakeProcess(exitCode: 1, stdout: 'stdout failure');
            default:
              return FakeProcess();
          }
        }, onRun: (List<String> command) {
          // Should not be executed.
          assert(false);
          return io.ProcessResult(81, 1, '', '');
        })),
        logger: logger,
      ),
      runHistory
    );
  }

  test('process queue success', () async {
    final Logger logger = Logger.test();
    final (Environment env, _) = macEnv(logger);
    final WorkerPool wp = WorkerPool(env, NoopWorkerPoolProgressReporter());
    final ProcessTask task =
        ProcessTask('S', env, io.Directory.current, <String>['success']);
    final bool r = await wp.run(<WorkerTask>{task});
    expect(r, equals(true));
    expect(task.processArtifacts.exitCode, equals(0));
    final ProcessArtifacts loaded =
        ProcessArtifacts.fromFile(io.File(task.processArtifactsPath));
    expect(loaded.stdout, equals('stdout success'));
  });

  test('process queue failure', () async {
    final Logger logger = Logger.test();
    final (Environment env, _) = macEnv(logger);
    final WorkerPool wp = WorkerPool(env, NoopWorkerPoolProgressReporter());
    final ProcessTask task =
        ProcessTask('F', env, io.Directory.current, <String>['failure']);
    final bool r = await wp.run(<WorkerTask>{task});
    expect(r, equals(false));
    expect(task.processArtifacts.exitCode, notEquals(0));
    final ProcessArtifacts loaded =
        ProcessArtifacts.fromFile(io.File(task.processArtifactsPath));
    expect(loaded.stdout, equals('stdout failure'));
  });
}
