// 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].
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);
}

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 ? new ConfigurationRegistry() : null,
        _resultCache = cacheSharedModules ? [] : null,
        super(steps, cacheSharedModules);

  @override
  Future<void> run(ModularTest test) async {
    _results = {};
    Map<Module, Map<DataId, Object>> cache = null;
    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) async {
    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) {
      module.sources.forEach((relativeUri) {
        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]);
    for (var dataId in step.resultData) {
      (_results[module] ??= {})[dataId] = result[dataId];
    }
  }
}
