/**
 * Creates a new UndoController. The undo controller manages an instance of
 * UndoManager and delegates all undo and redo commands to the undo manager.
 * 
 * @constructor
 * @param {mindmaps.EventBus} eventBus
 * @param {mindmaps.CommandRegistry} commandRegistry
 */
mindmaps.UndoController = function(eventBus, commandRegistry) {

  /**
   * Initialise.
   * 
   * @private
   */
  this.init = function() {
    this.undoManager = new UndoManager(128);
    this.undoManager.stateChanged = this.undoStateChanged.bind(this);

    this.undoCommand = commandRegistry.get(mindmaps.UndoCommand);
    this.undoCommand.setHandler(this.doUndo.bind(this));

    this.redoCommand = commandRegistry.get(mindmaps.RedoCommand);
    this.redoCommand.setHandler(this.doRedo.bind(this));

    eventBus.subscribe(mindmaps.Event.DOCUMENT_OPENED, this.documentOpened
        .bind(this));

    eventBus.subscribe(mindmaps.Event.DOCUMENT_CLOSED, this.documentClosed
        .bind(this));
  };

  /**
   * Handler for state changed event from undo manager.
   */
  this.undoStateChanged = function() {
    this.undoCommand.setEnabled(this.undoManager.canUndo());
    this.redoCommand.setEnabled(this.undoManager.canRedo());
  };

  /**
   * @see mindmaps.UndoManager#addUndo
   */
  this.addUndo = function(undoFunc, redoFunc) {
    this.undoManager.addUndo(undoFunc, redoFunc);
  };

  /**
   * Handler for undo command.
   */
  this.doUndo = function() {
    this.undoManager.undo();
  };

  /**
   * Handler for redo command.
   */
  this.doRedo = function() {
    this.undoManager.redo();
  };

  /**
   * Handler for document opened event.
   */
  this.documentOpened = function() {
    this.undoManager.reset();
    this.undoStateChanged();
  };

  /**
   * Handler for document closed event.
   */
  this.documentClosed = function() {
    this.undoManager.reset();
    this.undoStateChanged();
  };

  this.init();
};
