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