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

library barback.test.utils;

import 'dart:async';
import 'dart:collection';
import 'dart:convert' show Encoding;

import 'package:barback/barback.dart';
import 'package:barback/src/cancelable_future.dart';
import 'package:barback/src/utils.dart';
import 'package:path/path.dart' as pathos;
import 'package:scheduled_test/scheduled_test.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:unittest/compact_vm_config.dart';

export 'transformer/bad.dart';
export 'transformer/check_content.dart';
export 'transformer/check_content_and_rename.dart';
export 'transformer/create_asset.dart';
export 'transformer/many_to_one.dart';
export 'transformer/mock.dart';
export 'transformer/one_to_many.dart';
export 'transformer/rewrite.dart';

var _configured = false;

MockProvider _provider;
Barback _barback;

/// Calls to [buildShouldSucceed] and [buildShouldFail] set expectations on
/// successive [BuildResult]s from [_barback]. This keeps track of how many
/// calls have already been made so later calls know which result to look for.
int _nextBuildResult;

void initConfig() {
  if (_configured) return;
  _configured = true;
  useCompactVMConfiguration();
  filterStacks = true;
}

/// Creates a new [PackageProvider] and [PackageGraph] with the given [assets]
/// and [transformers].
///
/// This graph is used internally by most of the other functions in this
/// library so you must call it in the test before calling any of the other
/// functions.
///
/// [assets] may either be an [Iterable] or a [Map]. If it's an [Iterable],
/// each element may either be an [AssetId] or a string that can be parsed to
/// one. If it's a [Map], each key should be a string that can be parsed to an
/// [AssetId] and the value should be a string defining the contents of that
/// asset.
///
/// [transformers] is a map from package names to the transformers for each
/// package.
void initGraph([assets,
    Map<String, Iterable<Iterable<Transformer>>> transformers]) {
  if (assets == null) assets = [];
  if (transformers == null) transformers = {};

  var assetList;
  if (assets is Map) {
    assetList = assets.keys.map((asset) {
      var id = new AssetId.parse(asset);
      return new _MockAsset(id, assets[asset]);
    });
  } else if (assets is Iterable) {
    assetList = assets.map((asset) {
      var id = new AssetId.parse(asset);
      var contents = pathos.basenameWithoutExtension(id.path);
      return new _MockAsset(id, contents);
    });
  }

  var assetMap = mapMapValues(groupBy(assetList, (asset) => asset.id.package),
      (package, assets) => new AssetSet.from(assets));

  // Make sure that packages that have transformers but no assets are considered
  // by MockProvider to exist.
  for (var package in transformers.keys) {
    assetMap.putIfAbsent(package, () => new AssetSet());
  }

  _provider = new MockProvider(assetMap);
  _barback = new Barback(_provider);
  _nextBuildResult = 0;

  transformers.forEach(_barback.updateTransformers);

  // There should be one successful build after adding all the transformers but
  // before adding any sources.
  if (!transformers.isEmpty) buildShouldSucceed();
}

/// Updates [assets] in the current [PackageProvider].
///
/// Each item in the list may either be an [AssetId] or a string that can be
/// parsed as one.
void updateSources(Iterable assets) {
  assets = _parseAssets(assets);
  schedule(() => _barback.updateSources(assets),
      "updating ${assets.join(', ')}");
}

/// Updates [assets] in the current [PackageProvider].
///
/// Each item in the list may either be an [AssetId] or a string that can be
/// parsed as one. Unlike [updateSources], this is not automatically scheduled
/// and will be run synchronously when called.
void updateSourcesSync(Iterable assets) =>
    _barback.updateSources(_parseAssets(assets));

/// Removes [assets] from the current [PackageProvider].
///
/// Each item in the list may either be an [AssetId] or a string that can be
/// parsed as one.
void removeSources(Iterable assets) {
  assets = _parseAssets(assets);
  schedule(() => _barback.removeSources(assets),
      "removing ${assets.join(', ')}");
}

/// Removes [assets] from the current [PackageProvider].
///
/// Each item in the list may either be an [AssetId] or a string that can be
/// parsed as one. Unlike [removeSources], this is not automatically scheduled
/// and will be run synchronously when called.
void removeSourcesSync(Iterable assets) =>
    _barback.removeSources(_parseAssets(assets));

/// Sets the transformers for [package] to [transformers].
void updateTransformers(String package, Iterable<Iterable> transformers) {
  schedule(() => _barback.updateTransformers(package, transformers),
      "updating transformers for $package");
}

/// Parse a list of strings or [AssetId]s into a list of [AssetId]s.
List<AssetId> _parseAssets(Iterable assets) {
  return assets.map((asset) {
    if (asset is String) return new AssetId.parse(asset);
    return asset;
  }).toList();
}

/// Schedules a change to the contents of an asset identified by [name] to
/// [contents].
///
/// Does not update it in the graph.
void modifyAsset(String name, String contents) {
  schedule(() {
    _provider._modifyAsset(name, contents);
  }, "modify asset $name");
}

/// Schedules an error to be generated when loading the asset identified by
/// [name].
///
/// Does not update the asset in the graph.
void setAssetError(String name) {
  schedule(() {
    _provider._setAssetError(name);
  }, "set error for asset $name");
}

/// Schedules a pause of the internally created [PackageProvider].
///
/// All asset requests that the [PackageGraph] makes to the provider after this
/// will not complete until [resumeProvider] is called.
void pauseProvider() {
  schedule(() => _provider._pause(), "pause provider");
}

/// Schedules an unpause of the provider after a call to [pauseProvider] and
/// allows all pending asset loads to finish.
void resumeProvider() {
  schedule(() => _provider._resume(), "resume provider");
}

/// Asserts that the current build step shouldn't have finished by this point in
/// the schedule.
///
/// This uses the same build counter as [buildShouldSucceed] and
/// [buildShouldFail], so those can be used to validate build results before and
/// after this.
void buildShouldNotBeDone() {
  _futureShouldNotCompleteUntil(
      _barback.results.elementAt(_nextBuildResult),
      schedule(() => pumpEventQueue(), "build should not terminate"),
      "build");
}

/// Expects that the next [BuildResult] is a build success.
void buildShouldSucceed() {
  expect(_getNextBuildResult("build should succeed").then((result) {
    result.errors.forEach(currentSchedule.signalError);
    expect(result.succeeded, isTrue);
  }), completes);
}

/// Expects that the next [BuildResult] emitted is a failure.
///
/// [matchers] is a list of matchers to match against the errors that caused the
/// build to fail. Every matcher is expected to match an error, but the order of
/// matchers is unimportant.
void buildShouldFail(List matchers) {
  expect(_getNextBuildResult("build should fail").then((result) {
    expect(result.succeeded, isFalse);
    expect(result.errors.length, equals(matchers.length));
    for (var matcher in matchers) {
      expect(result.errors, contains(matcher));
    }
  }), completes);
}

Future<BuildResult> _getNextBuildResult(String description) {
  var result = currentSchedule.wrapFuture(
      _barback.results.elementAt(_nextBuildResult++));
  return schedule(() => result, description);
}

/// Schedules an expectation that the graph will deliver an asset matching
/// [name] and [contents].
///
/// If [contents] is omitted, defaults to the asset's filename without an
/// extension (which is the same default that [initGraph] uses).
void expectAsset(String name, [String contents]) {
  var id = new AssetId.parse(name);

  if (contents == null) {
    contents = pathos.basenameWithoutExtension(id.path);
  }

  schedule(() {
    return _barback.getAssetById(id).then((asset) {
      // TODO(rnystrom): Make an actual Matcher class for this.
      expect(asset.id, equals(id));
      expect(asset.readAsString(), completion(equals(contents)));
    });
  }, "get asset $name");
}

/// Schedules an expectation that the graph will not find an asset matching
/// [name].
void expectNoAsset(String name) {
  var id = new AssetId.parse(name);

  // Make sure the future gets the error.
  schedule(() {
    return _barback.getAssetById(id).then((asset) {
      fail("Should have thrown error but got $asset.");
    }).catchError((error) {
      expect(error, new isInstanceOf<AssetNotFoundException>());
      expect(error.id, equals(id));
    });
  }, "get asset $name");
}

/// Schedules an expectation that the graph will output all of the given
/// assets, and no others.
///
/// [assets] is a list of strings that can be parsed to [AssetID]s.
void expectAllAssets(Iterable<String> assets) {
  var expected = assets.map((asset) => new AssetId.parse(asset));

  schedule(() {
    return _barback.getAllAssets().then((actualAssets) {
      var actualIds = actualAssets.map((asset) => asset.id).toSet();

      for (var id in expected) {
        expect(actualIds, contains(id));
        actualIds.remove(id);
      }

      expect(actualIds, isEmpty);
    });
  }, "get all assets, expecting ${expected.join(', ')}");
}

/// Schedules an expectation that [Barback.getAllAssets] will return a [Future]
/// that completes to a error that matches [matcher].
///
/// If [match] is a [List], then it expects the completed error to be an
/// [AggregateException] whose errors match each matcher in the list. Otherwise,
/// [match] should be a single matcher that the error should match.
void expectAllAssetsShouldFail(Matcher matcher) {
  schedule(() {
    expect(_barback.getAllAssets(), throwsA(matcher));
  }, "get all assets should fail");
}

/// Schedules an expectation that a [getAssetById] call for the given asset
/// won't terminate at this point in the schedule.
void expectAssetDoesNotComplete(String name) {
  var id = new AssetId.parse(name);

  schedule(() {
    return _futureShouldNotCompleteUntil(
        _barback.getAssetById(id),
        pumpEventQueue(),
        "asset $id");
  }, "asset $id should not complete");
}

/// Returns a matcher for an [AggregateException] containing errors that match
/// [matchers].
Matcher isAggregateException(Iterable<Matcher> errors) {
  // Match the aggregate error itself.
  var matchers = [
    new isInstanceOf<AggregateException>(),
    transform((error) => error.errors, hasLength(errors.length),
        'errors.length == ${errors.length}')
  ];

  // Make sure its contained errors match the matchers.
  for (var error in errors) {
    matchers.add(transform((error) => error.errors, contains(error),
        error.toString()));
  }

  return allOf(matchers);
}

/// Returns a matcher for an [AssetNotFoundException] with the given [id].
Matcher isAssetNotFoundException(String name) {
  var id = new AssetId.parse(name);
  return allOf(
      new isInstanceOf<AssetNotFoundException>(),
      predicate((error) => error.id == id, 'id == $name'));
}

/// Returns a matcher for an [AssetCollisionException] with the given [id].
Matcher isAssetCollisionException(String name) {
  var id = new AssetId.parse(name);
  return allOf(
      new isInstanceOf<AssetCollisionException>(),
      predicate((error) => error.id == id, 'id == $name'));
}

/// Returns a matcher for a [MissingInputException] with the given [id].
Matcher isMissingInputException(String name) {
  var id = new AssetId.parse(name);
  return allOf(
      new isInstanceOf<MissingInputException>(),
      predicate((error) => error.id == id, 'id == $name'));
}

/// Returns a matcher for an [InvalidOutputException] with the given id.
Matcher isInvalidOutputException(String name) {
  var id = new AssetId.parse(name);
  return allOf(
      new isInstanceOf<InvalidOutputException>(),
      predicate((error) => error.id == id, 'id == $name'));
}

/// Returns a matcher for an [AssetLoadException] with the given id and a
/// wrapped error that matches [error].
Matcher isAssetLoadException(String name, error) {
  var id = new AssetId.parse(name);
  return allOf(
      new isInstanceOf<AssetLoadException>(),
      transform((error) => error.id, equals(id), 'id'),
      transform((error) => error.error, wrapMatcher(error), 'error'));
}

/// Returns a matcher for a [TransformerException] with a wrapped error that
/// matches [error].
Matcher isTransformerException(error) {
  return allOf(
      new isInstanceOf<TransformerException>(),
      transform((error) => error.error, wrapMatcher(error), 'error'));
}

/// Returns a matcher for a [MockLoadException] with the given [id].
Matcher isMockLoadException(String name) {
  var id = new AssetId.parse(name);
  return allOf(
      new isInstanceOf<MockLoadException>(),
      predicate((error) => error.id == id, 'id == $name'));
}

/// Returns a matcher that runs [transformation] on its input, then matches
/// the output against [matcher].
///
/// [description] should be a noun phrase that describes the relation of the
/// output of [transformation] to its input.
Matcher transform(transformation(value), matcher, String description) =>
  new _TransformMatcher(transformation, wrapMatcher(matcher), description);

class _TransformMatcher extends Matcher {
  final Function _transformation;
  final Matcher _matcher;
  final String _description;

  _TransformMatcher(this._transformation, this._matcher, this._description);

  bool matches(item, Map matchState) =>
    _matcher.matches(_transformation(item), matchState);

  Description describe(Description description) =>
    description.add(_description).add(' ').addDescriptionOf(_matcher);
}

/// Asserts that [future] shouldn't complete until after [delay] completes.
///
/// Once [delay] completes, the output of [future] is ignored, even if it's an
/// error.
///
/// [description] should describe [future].
Future _futureShouldNotCompleteUntil(Future future, Future delay,
    String description) {
  var trace = new Trace.current();
  var cancelable = new CancelableFuture(future);
  cancelable.then((result) {
    currentSchedule.signalError(
        new Exception("Expected $description not to complete here, but it "
            "completed with result: $result"),
        trace);
  }).catchError((error) {
    currentSchedule.signalError(error);
  });

  return delay.then((_) => cancelable.cancel());
}

/// An [AssetProvider] that provides the given set of assets.
class MockProvider implements PackageProvider {
  Iterable<String> get packages => _assets.keys;

  Map<String, AssetSet> _assets;

  /// The set of assets for which [MockLoadException]s should be emitted if
  /// they're loaded.
  final _errors = new Set<AssetId>();

  /// The completer that [getAsset()] is waiting on to complete when paused.
  ///
  /// If `null` it will return the asset immediately.
  Completer _pauseCompleter;

  /// Tells the provider to wait during [getAsset] until [complete()]
  /// is called.
  ///
  /// Lets you test the asynchronous behavior of loading.
  void _pause() {
    _pauseCompleter = new Completer();
  }

  void _resume() {
    _pauseCompleter.complete();
    _pauseCompleter = null;
  }

  MockProvider(this._assets) {
    // If there are no assets or transformers, add a dummy package. This better
    // simulates the real world, where there'll always be at least the
    // entrypoint package.
    if (_assets.isEmpty) {
      _assets = {"app": new AssetSet()};
    }
  }

  void _modifyAsset(String name, String contents) {
    var id = new AssetId.parse(name);
    _errors.remove(id);
    _assets[id.package][id].contents = contents;
  }

  void _setAssetError(String name) => _errors.add(new AssetId.parse(name));

  List<AssetId> listAssets(String package, {String within}) {
    if (within != null) {
      throw new UnimplementedError("Doesn't handle 'within' yet.");
    }

    return _assets[package].map((asset) => asset.id);
  }

  Future<Asset> getAsset(AssetId id) {
    // Eagerly load the asset so we can test an asset's value changing between
    // when a load starts and when it finishes.
    var assets = _assets[id.package];
    var asset;
    if (assets != null) asset = assets[id];

    var hasError = _errors.contains(id);

    var future;
    if (_pauseCompleter != null) {
      future = _pauseCompleter.future;
    } else {
      future = new Future.value();
    }

    return future.then((_) {
      if (hasError) throw new MockLoadException(id);
      if (asset == null) throw new AssetNotFoundException(id);
      return asset;
    });
  }
}

/// Error thrown for assets with [setAssetError] set.
class MockLoadException implements Exception {
  final AssetId id;

  MockLoadException(this.id);

  String toString() => "Error loading $id.";
}

/// An implementation of [Asset] that never hits the file system.
class _MockAsset implements Asset {
  final AssetId id;
  String contents;

  _MockAsset(this.id, this.contents);

  Future<String> readAsString({Encoding encoding}) =>
      new Future.value(contents);

  Stream<List<int>> read() => throw new UnimplementedError();

  String toString() => "MockAsset $id $contents";
}
