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

import 'dart:async';

import 'asset.dart';
import 'asset_id.dart';
import 'asset_node.dart';
import 'asset_set.dart';
import 'barback_logger.dart';
import 'errors.dart';
import 'phase.dart';
import 'transform.dart';
import 'transformer.dart';

/// Describes a transform on a set of assets and its relationship to the build
/// dependency graph.
///
/// Keeps track of whether it's dirty and needs to be run and which assets it
/// depends on.
class TransformNode {
  /// The [Phase] that this transform runs in.
  final Phase phase;

  /// The [Transformer] to apply to this node's inputs.
  final Transformer transformer;

  /// The node for the primary asset this transform depends on.
  final AssetNode primary;

  /// The subscription to [primary]'s [AssetNode.onStateChange] stream.
  StreamSubscription _primarySubscription;

  /// True if an input has been modified since the last time this transform
  /// began running.
  bool get isDirty => _isDirty;
  var _isDirty = true;

  /// The subscriptions to each input's [AssetNode.onStateChange] stream.
  var _inputSubscriptions = new Map<AssetId, StreamSubscription>();

  /// The controllers for the asset nodes emitted by this node.
  var _outputControllers = new Map<AssetId, AssetNodeController>();

  /// A stream that emits an event whenever this transform becomes dirty and
  /// needs to be re-run.
  ///
  /// This may emit events when the transform was already dirty or while
  /// processing transforms. Events are emitted synchronously to ensure that the
  /// dirty state is thoroughly propagated as soon as any assets are changed.
  Stream get onDirty => _onDirtyController.stream;
  final _onDirtyController = new StreamController.broadcast(sync: true);

  /// A stream that emits an event whenever this transform logs an entry.
  Stream<LogEntry> get onLog => _onLogController.stream;
  final _onLogController = new StreamController<LogEntry>.broadcast();

  TransformNode(this.phase, this.transformer, this.primary) {
    _primarySubscription = primary.onStateChange.listen((state) {
      if (state.isRemoved) {
        remove();
      } else {
        _dirty();
      }
    });
  }

  /// The [TransformInfo] describing this node.
  ///
  /// [TransformInfo] is the publicly-visible representation of a transform
  /// node.
  TransformInfo get info => new TransformInfo(transformer, primary.id);

  /// Marks this transform as removed.
  ///
  /// This causes all of the transform's outputs to be marked as removed as
  /// well. Normally this will be automatically done internally based on events
  /// from the primary input, but it's possible for a transform to no longer be
  /// valid even if its primary input still exists.
  void remove() {
    _isDirty = true;
    _onDirtyController.close();
    _primarySubscription.cancel();
    for (var subscription in _inputSubscriptions.values) {
      subscription.cancel();
    }
    for (var controller in _outputControllers.values) {
      controller.setRemoved();
    }
  }

  /// Marks this transform as dirty.
  ///
  /// This causes all of the transform's outputs to be marked as dirty as well.
  void _dirty() {
    _isDirty = true;
    for (var controller in _outputControllers.values) {
      controller.setDirty();
    }
    _onDirtyController.add(null);
  }

  /// Applies this transform.
  ///
  /// Returns a set of asset nodes representing the outputs from this transform
  /// that weren't emitted last time it was run.
  Future<Set<AssetNode>> apply() {
    assert(!_onDirtyController.isClosed);

    var newOutputs = new AssetSet();
    var transform = createTransform(this, newOutputs, _log);

    // Clear all the old input subscriptions. If an input is re-used, we'll
    // re-subscribe.
    for (var subscription in _inputSubscriptions.values) {
      subscription.cancel();
    }
    _inputSubscriptions.clear();

    _isDirty = false;
    return transformer.apply(transform).catchError((error) {
      // If the transform became dirty while processing, ignore any errors from
      // it.
      if (_isDirty) return;

      if (error is! MissingInputException) {
        error = new TransformerException(info, error);
      }

      // Catch all transformer errors and pipe them to the results stream.
      // This is so a broken transformer doesn't take down the whole graph.
      phase.cascade.reportError(error);

      // Don't allow partial results from a failed transform.
      newOutputs.clear();
    }).then((_) {
      if (_isDirty) return new Set();

      return _adjustOutputs(newOutputs);
    });
  }

  /// Gets the asset for an input [id].
  ///
  /// If an input with that ID cannot be found, throws an
  /// [AssetNotFoundException].
  Future<Asset> getInput(AssetId id) {
    return phase.getInput(id).then((node) {
      // Throw if the input isn't found. This ensures the transformer's apply
      // is exited. We'll then catch this and report it through the proper
      // results stream.
      if (node == null) throw new MissingInputException(info, id);

      // If the asset node is found, wait until its contents are actually
      // available before we return them.
      return node.whenAvailable.then((asset) {
        _inputSubscriptions.putIfAbsent(node.id,
            () => node.onStateChange.listen((_) => _dirty()));

        return asset;
      }).catchError((error) {
        if (error is! AssetNotFoundException || error.id != id) throw error;
        // If the node was removed before it could be loaded, treat it as though
        // it never existed and throw a MissingInputException.
        throw new MissingInputException(info, id);
      });
    });
  }

  /// Adjusts the outputs of the transform to reflect the outputs emitted on its
  /// most recent run.
  Set<AssetNode> _adjustOutputs(AssetSet newOutputs) {
    // Any ids that are for a different package are invalid.
    var invalidIds = newOutputs
        .map((asset) => asset.id)
        .where((id) => id.package != phase.cascade.package)
        .toSet();
    for (var id in invalidIds) {
      newOutputs.removeId(id);
      // TODO(nweiz): report this as a warning rather than a failing error.
      phase.cascade.reportError(new InvalidOutputException(info, id));
    }

    // Remove outputs that used to exist but don't anymore.
    for (var id in _outputControllers.keys.toList()) {
      if (newOutputs.containsId(id)) continue;
      _outputControllers.remove(id).setRemoved();
    }

    var brandNewOutputs = new Set<AssetNode>();
    // Store any new outputs or new contents for existing outputs.
    for (var asset in newOutputs) {
      var controller = _outputControllers[asset.id];
      if (controller != null) {
        controller.setAvailable(asset);
      } else {
        var controller = new AssetNodeController.available(asset, this);
        _outputControllers[asset.id] = controller;
        brandNewOutputs.add(controller.node);
      }
    }

    return brandNewOutputs;
  }

  void _log(AssetId asset, LogLevel level, String message, Span span) {
    // If the log isn't already associated with an asset, use the primary.
    if (asset == null) asset = primary.id;
    var info = new TransformInfo(transformer, primary.id);
    var entry = new LogEntry(info, asset, level, message, span);
    _onLogController.add(entry);
  }
}
