// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
// for details. 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:convert';
import 'dart:io';

import 'builder.dart';
import 'configuration.dart';

/// The manifest that defines the set of supported test [Configuration]s and
/// how they are run on the [Builders]s.
class TestMatrix {
  final List<Configuration> configurations;
  final List<Builder> builders;
  final List<String> branches;

  /// Reads a test matrix from the file at [path].
  static TestMatrix fromPath(String path) {
    var json = jsonDecode(File(path).readAsStringSync());
    return fromJson(json as Map<String, dynamic>);
  }

  static TestMatrix fromJson(Map<String, dynamic> json) {
    var configurationsJson =
        json["configurations"] as Map<String, dynamic>? ?? <String, dynamic>{};

    // Keep track of the configurations and which templates they were expanded
    // from.
    var configurations = <Configuration>[];

    configurationsJson.forEach((template, configurationJson) {
      var options = configurationJson["options"] ?? const <String, dynamic>{};

      for (var configuration in Configuration.expandTemplate(
          template, options as Map<String, dynamic>)) {
        for (var existing in configurations) {
          // Make sure the names don't collide.
          if (configuration.name == existing.name) {
            throw FormatException(
                'Configuration "${configuration.name}" already exists.');
          }

          // Make sure we don't have two equivalent configurations.
          if (configuration.optionsEqual(existing)) {
            throw FormatException(
                'Configuration "${configuration.name}" is identical to '
                '"${existing.name}".');
          }
        }

        configurations.add(configuration);
      }
    });

    var builderConfigurations = [
      ...?(json["builder_configurations"] as List<Object?>?)
          ?.cast<Map<Object?, Object?>>()
    ];
    var builders = parseBuilders(builderConfigurations, configurations);
    var branchesValue = json["branches"] as List?;
    var branches = [...?branchesValue?.cast<String>()];

    // Check that each configuration is tested on at most one builder.
    var testedOn = <Configuration, Builder>{};
    for (var builder in builders) {
      for (var configuration in builder.testedConfigurations) {
        var other = testedOn[configuration];
        if (other != null) {
          throw FormatException('Configuration "${configuration.name}" is '
              'tested on both "${builder.name}" and "${other.name}"');
        } else {
          testedOn[configuration] = builder;
        }
      }
    }

    return TestMatrix._(configurations, builders, branches);
  }

  TestMatrix._(this.configurations, this.builders, this.branches);
}
