// 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 excuted 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 exceuted 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";
}
