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

import 'package:engine_build_configs/engine_build_configs.dart';
import 'package:engine_repo_tools/engine_repo_tools.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
import 'package:process_runner/process_runner.dart';

// This is an example of how to use the APIs of this library to parse and
// execute the build configurations json files under ci/builders.
//
// Usage:
// $ dart bin/run.dart [build config name] [build name]
// For example:
// $ dart bin/run.dart mac_unopt host_debug_unopt
//
// The build config names are the names of the json files under ci/builders
// The build names are the "name" fields of the maps in the list of "builds".

void main(List<String> args) async {
  final String? configName;
  final String? buildName;
  if (args.length >= 2) {
    configName = args[0];
    buildName = args[1];
  } else {
    io.stderr.writeln(r'''
Usage:
$ dart bin/run.dart [build config name] [build name]

For example:

$ dart bin/run.dart mac_unopt host_debug_unopt

The build config names are the names of the json files under ci/builders.
The build names are the "name" fields of the maps in the list of "builds".
''');
    io.exitCode = 1;
    return;
  }

  // Find the engine repo.
  final Engine engine;
  try {
    engine = Engine.findWithin();
  } catch (e) {
    io.stderr.writeln(e);
    io.exitCode = 1;
    return;
  }

  // Find and parse the engine build configs.
  final io.Directory buildConfigsDir = io.Directory(p.join(
    engine.flutterDir.path, 'ci', 'builders',
  ));
  final BuildConfigLoader loader = BuildConfigLoader(
    buildConfigsDir: buildConfigsDir,
  );

  // Treat it as an error if no build configs were found. The caller likely
  // expected to find some.
  final Map<String, BuildConfig> configs = loader.configs;
  if (configs.isEmpty) {
    io.stderr.writeln(
      'Error: No build configs found under ${buildConfigsDir.path}',
    );
    io.exitCode = 1;
    return;
  }
  if (loader.errors.isNotEmpty) {
    loader.errors.forEach(io.stderr.writeln);
    io.exitCode = 1;
  }

  // Check the parsed build configs for validity.
  final BuildConfig? targetConfig = configs[configName];
  if (targetConfig == null) {
    io.stderr.writeln('Build config "$configName" not found.');
    io.exitCode = 1;
    return;
  }
  final List<String> buildConfigErrors = targetConfig.check(configName);
  if (buildConfigErrors.isNotEmpty) {
    io.stderr.writeln('Errors in "$configName":');
    for (final String error in buildConfigErrors) {
      io.stderr.writeln('    $error');
    }
    io.exitCode = 1;
    return;
  }

  GlobalBuild? targetBuild;
  for (int i = 0; i < targetConfig.builds.length; i++) {
    final GlobalBuild build = targetConfig.builds[i];
    if (build.name == buildName) {
      targetBuild = build;
    }
  }
  if (targetBuild == null) {
    io.stderr.writeln(
      'Target build not found. No build called $buildName in $configName',
    );
    io.exitCode = 1;
    return;
  }

  // If RBE config files aren't in the tree, then disable RBE.
  final String rbeConfigPath = p.join(
    engine.srcDir.path, 'flutter', 'build', 'rbe',
  );
  final List<String> extraGnArgs = <String>[
    if (!io.Directory(rbeConfigPath).existsSync()) '--no-rbe',
  ];

  final GlobalBuildRunner buildRunner = GlobalBuildRunner(
    platform: const LocalPlatform(),
    processRunner: ProcessRunner(),
    abi: ffi.Abi.current(),
    engineSrcDir: engine.srcDir,
    build: targetBuild,
    extraGnArgs: extraGnArgs,
    runGenerators: false,
    runTests: false,
  );
  void handler(RunnerEvent event) {
    switch (event) {
      case RunnerStart():
        io.stdout.writeln('$event: ${event.command.join(' ')}');
      case RunnerProgress(done: true):
        io.stdout.writeln(event);
      case RunnerProgress(done: false): {
        final int width = io.stdout.terminalColumns;
        final String percent = '${event.percent.toStringAsFixed(1)}%';
        final String fraction = '(${event.completed}/${event.total})';
        final String prefix = '[${event.name}] $percent $fraction ';
        final int remainingSpace = width - prefix.length;
        final String what;
        if (remainingSpace >= event.what.length) {
          what = event.what;
        } else {
          what = event.what.substring(event.what.length - remainingSpace + 1);
        }
        final String spaces = ' ' * width;
        io.stdout.write('$spaces\r');  // Erase the old line.
        io.stdout.write('$prefix$what\r'); // Print the new line.
      }
      default:
        io.stdout.writeln(event);
    }
  }
  final bool buildResult = await buildRunner.run(handler);
  io.exitCode = buildResult ? 0 : 1;
}
