// 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.

/// An implementation of [Pipeline] that runs in-memory.
///
/// To define a step, implement [MemoryModularStep].
library;

import 'pipeline.dart';
import 'suite.dart';

/// A hook to fetch data previously computed for a dependency.
typedef ModuleDataProvider = Object? Function(Module, DataId);
typedef SourceProvider = String? Function(Uri);

abstract class MemoryModularStep extends ModularStep {
  Future<Map<DataId, Object>> execute(
      Module module,
      SourceProvider sourceProvider,
      ModuleDataProvider dataProvider,
      List<String> flags);
}

class MemoryPipeline extends Pipeline<MemoryModularStep> {
  final Map<Uri, String> _sources;

  /// Internal state to hold the current results as they are computed by the
  /// pipeline. Expected to be null before and after the pipeline runs.
  Map<Module, Map<DataId, Object>>? _results;

  /// A copy of [_result] at the time the pipeline last finished running.
  Map<Module, Map<DataId, Object>>? resultsForTesting;

  final ConfigurationRegistry? _registry;

  /// Cache of results when [cacheSharedModules] is true
  final List<Map<Module, Map<DataId, Object>>> _resultCache;

  MemoryPipeline(this._sources, List<MemoryModularStep> steps,
      {bool cacheSharedModules = false})
      : _registry = cacheSharedModules ? ConfigurationRegistry() : null,
        _resultCache = cacheSharedModules ? [] : const [],
        super(steps, cacheSharedModules);

  @override
  Future<void> run(ModularTest test) async {
    var results = _results = {};
    Map<Module, Map<DataId, Object>>? cache;
    if (cacheSharedModules) {
      int id = _registry!.computeConfigurationId(test);
      if (id < _resultCache.length) {
        cache = _resultCache[id];
      } else {
        assert(id == _resultCache.length);
        _resultCache.add(cache = {});
      }
      results.addAll(cache);
    }
    await super.run(test);
    resultsForTesting = results;
    if (cacheSharedModules) {
      for (var module in results.keys) {
        if (module.isShared) {
          cache![module] = results[module]!;
        }
      }
    }
    _results = null;
  }

  @override
  Future<void> runStep(MemoryModularStep step, Module module,
      Map<Module, Set<DataId>> visibleData, List<String> flags) async {
    final results = _results!;
    if (cacheSharedModules && module.isShared) {
      bool allCachedResultsFound = true;
      for (var dataId in step.resultData) {
        if (results[module] == null || results[module]![dataId] == null) {
          allCachedResultsFound = false;
          break;
        }
      }
      if (allCachedResultsFound) {
        step.notifyCached(module);
        return;
      }
    }

    Map<Module, Map<DataId, Object>> inputData = {};
    visibleData.forEach((module, dataIdSet) {
      inputData[module] = {};
      for (var dataId in dataIdSet) {
        inputData[module]![dataId] = results[module]![dataId]!;
      }
    });
    Map<Uri, String> inputSources = {};
    if (step.needsSources) {
      for (var relativeUri in module.sources) {
        var uri = module.rootUri.resolveUri(relativeUri);
        inputSources[uri] = _sources[uri]!;
      }
    }
    Map<DataId, Object> result = await step.execute(
        module,
        (Uri uri) => inputSources[uri],
        (Module m, DataId id) => inputData[m]![id],
        flags);
    for (var dataId in step.resultData) {
      (results[module] ??= {})[dataId] = result[dataId]!;
    }
  }
}
