// 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:io' as io show Directory, exitCode, stderr;

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';

// Usage:
// $ dart bin/check.dart [/path/to/engine/src]

void main(List<String> args) {
  final String? engineSrcPath;
  if (args.isNotEmpty) {
    engineSrcPath = args[0];
  } else {
    engineSrcPath = null;
  }

  // Find the engine repo.
  final Engine engine;
  try {
    engine = Engine.findWithin(engineSrcPath);
  } 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, BuilderConfig> 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 List<String> invalidErrors = checkForInvalidConfigs(configs);
  if (invalidErrors.isNotEmpty) {
    invalidErrors.forEach(io.stderr.writeln);
    io.exitCode = 1;
  }

  // We require all builds within a builder config to be uniquely named.
  final List<String> duplicateErrors = checkForDuplicateConfigs(configs);
  if (duplicateErrors.isNotEmpty) {
    duplicateErrors.forEach(io.stderr.writeln);
    io.exitCode = 1;
  }

  // We require all builds to be named in a way that is understood by et.
  final List<String> buildNameErrors = checkForInvalidBuildNames(configs);
  if (buildNameErrors.isNotEmpty) {
    buildNameErrors.forEach(io.stderr.writeln);
    io.exitCode = 1;
  }
}

// This check ensures that all the json files were deserialized without errors.
List<String> checkForInvalidConfigs(Map<String, BuilderConfig> configs) {
  final List<String> errors = <String>[];
  for (final String name in configs.keys) {
    final BuilderConfig buildConfig = configs[name]!;
    final List<String> buildConfigErrors = buildConfig.check(name);
    if (buildConfigErrors.isNotEmpty) {
      errors.add('Errors in ${buildConfig.path}:');
    }
    for (final String error in buildConfigErrors) {
      errors.add('    $error');
    }
  }
  return errors;
}

// Thjs check ensures that json files do not contain builds with duplicate
// names.
List<String> checkForDuplicateConfigs(Map<String, BuilderConfig> configs) {
  final List<String> errors = <String>[];
  final Map<String, Set<String>> builderBuildSet = <String, Set<String>>{};
  _forEachBuild(configs, (String name, BuilderConfig config, Build build) {
    final Set<String> builds = builderBuildSet.putIfAbsent(name, () => <String>{});
    if (builds.contains(build.name)) {
      errors.add('${build.name} is duplicated in $name\n');
    } else {
      builds.add(build.name);
    }
  });
  return errors;
}

// This check ensures that builds are named in a way that is understood by
// `et`.
List<String> checkForInvalidBuildNames(Map<String, BuilderConfig> configs) {
  final List<String> errors = <String>[];

  // In local_engine.json, allowed OS names are linux, macos, and windows.
  final List<String> osNames = <String>[
    Platform.linux, Platform.macOS, Platform.windows,
  ].expand((String s) => <String>['$s/', '$s\\']).toList();

  // In all other build json files, allowed prefix names are ci and web_tests.
  final List<String> ciNames = <String>[
    'ci', 'web_tests'
  ].expand((String s) => <String>['$s/', '$s\\']).toList();

  _forEachBuild(configs, (String name, BuilderConfig config, Build build) {
    final List<String> goodPrefixes = name.contains('local_engine')
      ? osNames
      : ciNames;
    if (!goodPrefixes.any(build.name.startsWith)) {
      if (name.contains('local_engine')) {
        // TODO(zanderso): Check these builds as well after local_engine is
        // fixed.
        // https://github.com/flutter/flutter/issues/145263
        return;
      }
      errors.add(
        '${build.name} in $name must start with one of '
        '{${goodPrefixes.join(', ')}}',
      );
    }
  });
  return errors;
}

void _forEachBuild(
  Map<String, BuilderConfig> configs,
  void Function(String configName, BuilderConfig config, Build build) fn,
) {
  for (final String builderName in configs.keys) {
    final BuilderConfig builderConfig = configs[builderName]!;
    for (final Build build in builderConfig.builds) {
      fn(builderName, builderConfig, build);
    }
  }
}
