// 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 dependency_graph;

import 'dart:async';
import 'utils.dart';


/*
 * [Graph] represents a datastructure for representing an DAG (directed acyclic
 * graph). Each node in the graph is in a given [NodeState] and can have data
 * attachted to it with [Node.userData].
 *
 * It's interface consists basically of these methods:
 *   - newNode: Adds a new node to the graph with the given dependencies and
 *              the given user data. The node is in the [NodeState.Initialized]
 *              state.
 *   - changeState: Changes the state of a node.
 *   - sealGraph: Makes the graph immutable.
 *   - stateCount: Counts the number of nodes who are in a given [NodeState].
 *
 * Users of a [Graph] can listen for events by subscribing to the [events]
 * stream. Three types of events will be fired (after the graph was modified):
 *   - NodeAddedEvent: Fired after a node was added ot the graph.
 *   - StateChangedEvent: Fired after the state of a node changed.
 *   - GraphSealedEvent: Fired after the graph was marked as immutable/sealed.
 */
class Graph {
  final _nodes = new Set<Node>();
  final _eventController = new StreamController<GraphEvent>();
  final _stateCounts = new Map<NodeState, int>();
  var _eventStream;
  bool _isSealed = false;

  Graph() {
    _eventStream = _eventController.stream.asBroadcastStream();
  }

  Iterable<Node> get nodes => _nodes;
  Stream<GraphEvent> get events => _eventStream;
  bool get isSealed => _isSealed;

  int stateCount(NodeState state) {
    int count = _stateCounts[state];
    return count == null ? 0 : count;
  }

  void DumpCounts() {
    for (var state in _stateCounts.keys) {
      print("Count[$state] = ${_stateCounts[state]}");
    }
  }

  void sealGraph() {
    assert(!_isSealed);
    _isSealed = true;
    _emitEvent(new GraphSealedEvent());
  }

  Node newNode(Object userData, Iterable<Node> dependencies) {
    assert(!_isSealed);

    var node = new Node._(userData);
    _nodes.add(node);

    for (var dependency in dependencies) {
      dependency._neededFor.add(node);
      node._dependencies.add(dependency);
    }

    _emitEvent(new NodeAddedEvent(node));

    _stateCounts.putIfAbsent(node.state, () => 0);
    _stateCounts[node.state] += 1;

    return node;
  }

  void changeState(Node node, NodeState newState) {
    var fromState = node.state;
    node._state = newState;

    _stateCounts[fromState] -= 1;
    _stateCounts.putIfAbsent(newState, () => 0);
    _stateCounts[newState] += 1;

    _emitEvent(new StateChangedEvent(node, fromState, newState));
  }

  _emitEvent(GraphEvent event) {
    // We emit events asynchronously so the graph can be build up in small
    // batches and the events are delivered in small batches.
    Timer.run(() {
      _eventController.add(event);
    });
  }
}

class Node extends UniqueObject {
  final Object _userData;
  NodeState _state = NodeState.Initialized;
  Set<Node> _dependencies = new Set<Node>();
  Set<Node> _neededFor = new Set<Node>();

  Node._(this._userData);

  Object get userData => _userData;
  NodeState get state => _state;
  Iterable<Node> get dependencies => _dependencies;
  Iterable<Node> get neededFor => _neededFor;
}

class NodeState extends UniqueObject {
  static NodeState Initialized = new NodeState._("Initialized");
  static NodeState Waiting  = new NodeState._("Waiting");
  static NodeState Enqueuing  = new NodeState._("Enqueuing");
  static NodeState Processing  = new NodeState._("Running");
  static NodeState Successful  = new NodeState._("Successful");
  static NodeState Failed  = new NodeState._("Failed");
  static NodeState UnableToRun  = new NodeState._("UnableToRun");

  final String name;

  NodeState._(this.name);

  String toString() => name;
}

abstract class GraphEvent {}

class GraphSealedEvent extends GraphEvent {}

class NodeAddedEvent extends GraphEvent {
  final Node node;

  NodeAddedEvent(this.node);
}

class StateChangedEvent extends GraphEvent {
  final Node node;
  final NodeState from;
  final NodeState to;

  StateChangedEvent(this.node, this.from, this.to);
}
