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

/// Unit test for in-memory pipelines.
import 'dart:async';

import 'package:modular_test/src/memory_pipeline.dart';

import 'pipeline_common.dart';

main() {
  runPipelineTest(new MemoryPipelineTestStrategy());
}

/// The strategy implementation to exercise the pipeline test on a
/// [MemoryPipeline].
class MemoryPipelineTestStrategy
    implements PipelineTestStrategy<MemoryModularStep> {
  @override
  Uri get testRootUri => Uri.parse('/');

  @override
  FutureOr<Pipeline<MemoryModularStep>> createPipeline(
      Map<Uri, String> sources, List<MemoryModularStep> steps,
      {bool cacheSharedModules: false}) {
    return new MemoryPipeline(sources, steps,
        cacheSharedModules: cacheSharedModules);
  }

  @override
  MemoryModularStep createSourceOnlyStep(
          {required String Function(Map<Uri, String?>) action,
          required DataId resultId,
          bool requestSources: true}) =>
      SourceOnlyStep(action, resultId, requestSources);

  @override
  MemoryModularStep createModuleDataStep(
          {required String Function(String) action,
          required DataId inputId,
          required DataId resultId,
          bool requestModuleData: true}) =>
      ModuleDataStep(action, inputId, resultId, requestModuleData);

  @override
  MemoryModularStep createLinkStep(
          {required String Function(String, List<String?>) action,
          required DataId inputId,
          required DataId depId,
          required DataId resultId,
          bool requestDependenciesData: true}) =>
      LinkStep(action, inputId, depId, resultId, requestDependenciesData);

  @override
  MemoryModularStep createMainOnlyStep(
          {required String Function(String, List<String?>) action,
          required DataId inputId,
          required DataId depId,
          required DataId resultId,
          bool requestDependenciesData: true}) =>
      MainOnlyStep(action, inputId, depId, resultId, requestDependenciesData);

  @override
  MemoryModularStep createTwoOutputStep(
          {required String Function(String) action1,
          required String Function(String) action2,
          required DataId inputId,
          required DataId result1Id,
          required DataId result2Id}) =>
      TwoOutputStep(action1, action2, inputId, result1Id, result2Id);

  @override
  String? getResult(
      covariant MemoryPipeline pipeline, Module m, DataId dataId) {
    return pipeline.resultsForTesting![m]![dataId] as String?;
  }

  FutureOr<void> cleanup(Pipeline<MemoryModularStep> pipeline) => null;
}

class SourceOnlyStep implements MemoryModularStep {
  final String Function(Map<Uri, String?>) action;
  final DataId resultId;
  final bool needsSources;
  List<DataId> get dependencyDataNeeded => const [];
  List<DataId> get moduleDataNeeded => const [];
  List<DataId> get resultData => [resultId];
  bool get onlyOnMain => false;
  bool get onlyOnSdk => false;
  bool get notOnSdk => false;

  SourceOnlyStep(this.action, this.resultId, this.needsSources);

  Future<Map<DataId, Object>> execute(
      Module module,
      SourceProvider sourceProvider,
      ModuleDataProvider dataProvider,
      List<String> flags) {
    Map<Uri, String?> sources = {};
    for (var uri in module.sources) {
      sources[uri] = sourceProvider(module.rootUri.resolveUri(uri));
    }
    return Future.value({resultId: action(sources)});
  }

  @override
  void notifyCached(Module module) {}
}

class ModuleDataStep implements MemoryModularStep {
  final String Function(String) action;
  bool get needsSources => false;
  List<DataId> get dependencyDataNeeded => const [];
  final List<DataId> moduleDataNeeded;
  List<DataId> get resultData => [resultId];
  final DataId resultId;
  final DataId inputId;
  bool get onlyOnMain => false;
  bool get onlyOnSdk => false;
  bool get notOnSdk => false;

  ModuleDataStep(this.action, this.inputId, this.resultId, bool requestInput)
      : moduleDataNeeded = requestInput ? [inputId] : [];

  Future<Map<DataId, Object>> execute(
      Module module,
      SourceProvider sourceProvider,
      ModuleDataProvider dataProvider,
      List<String> flags) {
    var inputData = dataProvider(module, inputId) as String?;
    if (inputData == null) {
      return Future.value({resultId: "data for $module was null"});
    }
    return Future.value({resultId: action(inputData)});
  }

  @override
  void notifyCached(Module module) {}
}

class TwoOutputStep implements MemoryModularStep {
  final String Function(String) action1;
  final String Function(String) action2;
  bool get needsSources => false;
  List<DataId> get dependencyDataNeeded => const [];
  List<DataId> get moduleDataNeeded => [inputId];
  List<DataId> get resultData => [result1Id, result2Id];
  final DataId result1Id;
  final DataId result2Id;
  final DataId inputId;
  bool get onlyOnMain => false;
  bool get onlyOnSdk => false;
  bool get notOnSdk => false;

  TwoOutputStep(
      this.action1, this.action2, this.inputId, this.result1Id, this.result2Id);

  Future<Map<DataId, Object>> execute(
      Module module,
      SourceProvider sourceProvider,
      ModuleDataProvider dataProvider,
      List<String> flags) {
    var inputData = dataProvider(module, inputId) as String?;
    if (inputData == null) {
      return Future.value({
        result1Id: "result for $module was null",
        result2Id: "result for $module was null",
      });
    }
    return Future.value(
        {result1Id: action1(inputData), result2Id: action2(inputData)});
  }

  @override
  void notifyCached(Module module) {}
}

class LinkStep implements MemoryModularStep {
  bool get needsSources => false;
  final List<DataId> dependencyDataNeeded;
  List<DataId> get moduleDataNeeded => [inputId];
  final String Function(String, List<String?>) action;
  final DataId inputId;
  final DataId depId;
  final DataId resultId;
  List<DataId> get resultData => [resultId];
  bool get onlyOnMain => false;
  bool get onlyOnSdk => false;
  bool get notOnSdk => false;

  LinkStep(this.action, this.inputId, this.depId, this.resultId,
      bool requestDependencies)
      : dependencyDataNeeded = requestDependencies ? [depId] : [];

  Future<Map<DataId, Object>> execute(
      Module module,
      SourceProvider sourceProvider,
      ModuleDataProvider dataProvider,
      List<String> flags) {
    List<String> depsData = module.dependencies
        .map((d) => dataProvider(d, depId).toString())
        .toList();
    var inputData = dataProvider(module, inputId).toString();
    return Future.value({resultId: action(inputData, depsData)});
  }

  @override
  void notifyCached(Module module) {}
}

class MainOnlyStep implements MemoryModularStep {
  bool get needsSources => false;
  final List<DataId> dependencyDataNeeded;
  List<DataId> get moduleDataNeeded => [inputId];
  final String Function(String, List<String?>) action;
  final DataId inputId;
  final DataId depId;
  final DataId resultId;
  List<DataId> get resultData => [resultId];
  bool get onlyOnMain => true;
  bool get onlyOnSdk => false;
  bool get notOnSdk => false;

  MainOnlyStep(this.action, this.inputId, this.depId, this.resultId,
      bool requestDependencies)
      : dependencyDataNeeded = requestDependencies ? [depId] : [];

  Future<Map<DataId, Object>> execute(
      Module module,
      SourceProvider sourceProvider,
      ModuleDataProvider dataProvider,
      List<String> flags) {
    List<String?> depsData = computeTransitiveDependencies(module)
        .map((d) => dataProvider(d, depId) as String?)
        .toList();
    var inputData = dataProvider(module, inputId) as String?;
    return Future.value({resultId: action(inputData!, depsData)});
  }

  @override
  void notifyCached(Module module) {}
}
