text: /**
   * Copyright 2013-2014 Facebook, Inc.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   * @providesModule ReactReconcileTransaction
   * @typechecks static-only
   */
  
  "use strict";
  
  var CallbackQueue = require('CallbackQueue');
  var PooledClass = require('PooledClass');
  var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
  var ReactInputSelection = require('ReactInputSelection');
  var ReactPutListenerQueue = require('ReactPutListenerQueue');
  var Transaction = require('Transaction');
  
  var mixInto = require('mixInto');
  
  /**
   * Ensures that, when possible, the selection range (currently selected text
   * input) is not disturbed by performing the transaction.
   */
  var SELECTION_RESTORATION = {
    /**
     * @return {Selection} Selection information.
     */
    initialize: ReactInputSelection.getSelectionInformation,
    /**
     * @param {Selection} sel Selection information returned from `initialize`.
     */
    close: ReactInputSelection.restoreSelection
  };
  
  /**
   * Suppresses events (blur/focus) that could be inadvertently dispatched due to
   * high level DOM manipulations (like temporarily removing a text input from the
   * DOM).
   */
  var EVENT_SUPPRESSION = {
    /**
     * @return {boolean} The enabled status of `ReactBrowserEventEmitter` before
     * the reconciliation.
     */
    initialize: function() {
      var currentlyEnabled = ReactBrowserEventEmitter.isEnabled();
      ReactBrowserEventEmitter.setEnabled(false);
      return currentlyEnabled;
    },
  
    /**
     * @param {boolean} previouslyEnabled Enabled status of
     *   `ReactBrowserEventEmitter` before the reconciliation occured. `close`
     *   restores the previous value.
     */
    close: function(previouslyEnabled) {
      ReactBrowserEventEmitter.setEnabled(previouslyEnabled);
    }
  };
  
  /**
   * Provides a queue for collecting `componentDidMount` and
   * `componentDidUpdate` callbacks during the the transaction.
   */
  var ON_DOM_READY_QUEUEING = {
    /**
     * Initializes the internal `onDOMReady` queue.
     */
    initialize: function() {
      this.reactMountReady.reset();
    },
  
    /**
     * After DOM is flushed, invoke all registered `onDOMReady` callbacks.
     */
    close: function() {
      this.reactMountReady.notifyAll();
    }
  };
  
  var PUT_LISTENER_QUEUEING = {
    initialize: function() {
      this.putListenerQueue.reset();
    },
  
    close: function() {
      this.putListenerQueue.putListeners();
    }
  };
  
  /**
   * Executed within the scope of the `Transaction` instance. Consider these as
   * being member methods, but with an implied ordering while being isolated from
   * each other.
   */
  var TRANSACTION_WRAPPERS = [
    PUT_LISTENER_QUEUEING,
    SELECTION_RESTORATION,
    EVENT_SUPPRESSION,
    ON_DOM_READY_QUEUEING
  ];
  
  /**
   * Currently:
   * - The order that these are listed in the transaction is critical:
   * - Suppresses events.
   * - Restores selection range.
   *
   * Future:
   * - Restore document/overflow scroll positions that were unintentionally
   *   modified via DOM insertions above the top viewport boundary.
   * - Implement/integrate with customized constraint based layout system and keep
   *   track of which dimensions must be remeasured.
   *
   * @class ReactReconcileTransaction
   */
  function ReactReconcileTransaction() {
    this.reinitializeTransaction();
    // Only server-side rendering really needs this option (see
    // `ReactServerRendering`), but server-side uses
    // `ReactServerRenderingTransaction` instead. This option is here so that it's
    // accessible and defaults to false when `ReactDOMComponent` and
    // `ReactTextComponent` checks it in `mountComponent`.`
    this.renderToStaticMarkup = false;
    this.reactMountReady = CallbackQueue.getPooled(null);
    this.putListenerQueue = ReactPutListenerQueue.getPooled();
  }
  
  var Mixin = {
    /**
     * @see Transaction
     * @abstract
     * @final
     * @return {array<object>} List of operation wrap proceedures.
     *   TODO: convert to array<TransactionWrapper>
     */
    getTransactionWrappers: function() {
      return TRANSACTION_WRAPPERS;
    },
  
    /**
     * @return {object} The queue to collect `onDOMReady` callbacks with.
     */
    getReactMountReady: function() {
      return this.reactMountReady;
    },
  
    getPutListenerQueue: function() {
      return this.putListenerQueue;
    },
  
    /**
     * `PooledClass` looks for this, and will invoke this before allowing this
     * instance to be resused.
     */
    destructor: function() {
      CallbackQueue.release(this.reactMountReady);
      this.reactMountReady = null;
  
      ReactPutListenerQueue.release(this.putListenerQueue);
      this.putListenerQueue = null;
    }
  };
  
  
  mixInto(ReactReconcileTransaction, Transaction.Mixin);
  mixInto(ReactReconcileTransaction, Mixin);
  
  PooledClass.addPoolingTo(ReactReconcileTransaction);
  
  module.exports = ReactReconcileTransaction;
  