// Copyright (c) 2019, 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.

/// Abstraction for a compilation pipeline.
///
/// A pipeline defines how modular steps are executed and ensures that a step
/// only has access to the data it declares.
///
/// The abstract implementation validates how the data is declared, and the
/// underlying implementations enforce the access to data in different ways.
///
/// The IO-based implementation ensures hermeticity by copying data to different
/// directories. The memory-based implementation ensures hemeticity by filtering
/// out the data before invoking the next step.
import 'suite.dart';

/// Describes a step in a modular compilation pipeline.
class ModularStep {
  /// Whether this step needs to read the source files in the module.
  final bool needsSources;

  /// Data that this step needs to read about dependencies.
  ///
  /// This can be data produced on a previous stage of the pipeline
  /// or produced by this same step when it was run on a dependency.
  ///
  /// If this list includes any data from [resultData], then the modular-step
  /// has to be run on dependencies before it is run on a module. Otherwise, it
  /// could be run in parallel.
  final List<DataId> dependencyDataNeeded;

  /// Data that this step needs to read about the module itself.
  ///
  /// This is meant to be data produced in earlier stages of the modular
  /// pipeline. It is an error to include any id from [resultData] in this list.
  final List<DataId> moduleDataNeeded;

  /// Data that this step produces.
  final List<DataId> resultData;

  /// Whether this step is only executed on the main module.
  final bool onlyOnMain;

  /// Whether this step is only executed on the SDK.
  final bool onlyOnSdk;

  /// Whether this step is not executed on the SDK.
  final bool notOnSdk;

  ModularStep(
      {this.needsSources = true,
      this.dependencyDataNeeded = const [],
      this.moduleDataNeeded = const [],
      this.resultData = const [],
      this.onlyOnMain = false,
      this.onlyOnSdk = false,
      this.notOnSdk = false});

  /// Notifies that the step was not executed, but cached instead.
  void notifyCached(Module module) {}
}

/// An object to uniquely identify modular data produced by a modular step.
///
/// Two modular steps on the same pipeline cannot emit the same data.
class DataId {
  final String name;

  const DataId(this.name);

  @override
  String toString() => name;
}

abstract class Pipeline<S extends ModularStep> {
  /// Whether to cache the result of shared modules (e.g. shard packages and sdk
  /// libraries) when multiple tests are run by this pipeline.
  final bool cacheSharedModules;

  final List<S> steps;

  Pipeline(this.steps, this.cacheSharedModules) {
    _validate();
  }

  void _validate() {
    // Whether or not two steps run on mutually exclusive input data.
    bool areMutuallyExclusive(S a, S b) {
      return (a.onlyOnSdk && b.notOnSdk) || (b.onlyOnSdk && a.notOnSdk);
    }

    // Ensure that steps consume only data that was produced by previous steps
    // or by the same step on a dependency.
    Map<DataId, S> previousKinds = {};
    for (var step in steps) {
      if (step.resultData.isEmpty) {
        _validationError(
            "'${step.runtimeType}' needs to declare what data it produces.");
      }
      for (var resultKind in step.resultData) {
        if (previousKinds.containsKey(resultKind) &&
            !areMutuallyExclusive(step, previousKinds[resultKind]!)) {
          _validationError("Cannot produce the same data on two modular steps."
              " '$resultKind' was previously produced by "
              "'${previousKinds[resultKind].runtimeType}' but "
              "'${step.runtimeType}' also produces the same data.");
        }
        previousKinds[resultKind] = step;
        for (var dataId in step.dependencyDataNeeded) {
          if (!previousKinds.containsKey(dataId)) {
            _validationError(
                "Step '${step.runtimeType}' needs data '${dataId}', but the "
                "data is not produced by this or a preceding step.");
          }
        }
        for (var dataId in step.moduleDataNeeded) {
          if (!previousKinds.containsKey(dataId)) {
            _validationError(
                "Step '${step.runtimeType}' needs data '${dataId}', but the "
                "data is not produced by a preceding step.");
          }
          if (dataId == resultKind) {
            _validationError("Circular dependency on '$dataId' "
                "in step '${step.runtimeType}'");
          }
        }
      }
    }
  }

  void _validationError(String s) => throw InvalidPipelineError(s);

  Future<void> run(ModularTest test) async {
    // TODO(sigmund): validate that [ModularTest] has no cycles.
    Map<Module, Set<DataId>> computedData = {};
    for (var step in steps) {
      await _recursiveRun(step, test.mainModule, computedData, {}, test.flags);
    }
  }

  Future<void> _recursiveRun(
      S step,
      Module module,
      Map<Module, Set<DataId>> computedData,
      Map<Module, Set<Module>> transitiveDependencies,
      List<String> flags) async {
    if (transitiveDependencies.containsKey(module)) return;
    var deps = transitiveDependencies[module] = {};
    for (var dependency in module.dependencies) {
      await _recursiveRun(
          step, dependency, computedData, transitiveDependencies, flags);
      deps.add(dependency);
      deps.addAll(transitiveDependencies[dependency]!);
    }

    if ((step.onlyOnMain && !module.isMain) ||
        (step.onlyOnSdk && !module.isSdk) ||
        (step.notOnSdk && module.isSdk)) return;
    // Include only requested data from transitive dependencies.
    Map<Module, Set<DataId>> visibleData = {};

    deps.forEach((dep) {
      visibleData[dep] = {};
      for (var dataId in step.dependencyDataNeeded) {
        if (computedData[dep]!.contains(dataId)) {
          visibleData[dep]!.add(dataId);
        }
      }
    });
    visibleData[module] = {};
    for (var dataId in step.moduleDataNeeded) {
      if (computedData[module]!.contains(dataId)) {
        visibleData[module]!.add(dataId);
      }
    }
    await runStep(step, module, visibleData, flags);
    (computedData[module] ??= {}).addAll(step.resultData);
  }

  Future<void> runStep(S step, Module module,
      Map<Module, Set<DataId>> visibleData, List<String> flags);
}

class InvalidPipelineError extends Error {
  final String message;
  InvalidPipelineError(this.message);
  String toString() => "Invalid pipeline: $message";
}
