text: /*!
   * Module dependencies.
   */
  
  var Document = require('../document')
    , inspect = require('util').inspect;
  
  /**
   * EmbeddedDocument constructor.
   *
   * @param {Object} obj js object returned from the db
   * @param {MongooseDocumentArray} parentArr the parent array of this document
   * @param {Boolean} skipId
   * @inherits Document
   * @api private
   */
  
  function EmbeddedDocument (obj, parentArr, skipId) {
    if (parentArr) {
      this.__parentArray = parentArr;
      this.__parent = parentArr._parent;
    } else {
      this.__parentArray = undefined;
      this.__parent = undefined;
    }
  
    Document.call(this, obj, undefined, skipId);
  
    var self = this;
    this.on('isNew', function (val) {
      self.isNew = val;
    });
  };
  
  /*!
   * Inherit from Document
   */
  
  EmbeddedDocument.prototype.__proto__ = Document.prototype;
  
  /**
   * Marks the embedded doc modified.
   *
   * ####Example:
   *
   *     var doc = blogpost.comments.id(hexstring);
   *     doc.mixed.type = 'changed';
   *     doc.markModified('mixed.type');
   *
   * @param {String} path the path which changed
   * @api public
   */
  
  EmbeddedDocument.prototype.markModified = function (path) {
    if (!this.__parentArray) return;
  
    this._activePaths.modify(path);
  
    if (this.isNew) {
      // Mark the WHOLE parent array as modified
      // if this is a new document (i.e., we are initializing
      // a document),
      this.__parentArray._markModified();
    } else
      this.__parentArray._markModified(this, path);
  };
  
  /**
   * Used as a stub for [hooks.js](https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3)
   *
   * ####NOTE:
   *
   * _This is a no-op. Does not actually save the doc to the db._
   *
   * @param {Function} [fn]
   * @return {EmbeddedDocument} this
   * @api private
   */
  
  EmbeddedDocument.prototype.save = function(fn) {
    if (fn)
      fn(null);
    return this;
  };
  
  /**
   * Removes the subdocument from its parent array.
   *
   * @param {Function} [fn]
   * @api public
   */
  
  EmbeddedDocument.prototype.remove = function (fn) {
    if (!this.__parentArray) return this;
  
    var _id;
    if (!this.willRemove) {
      _id = this._doc._id;
      if (!_id) {
        throw new Error('For your own good, Mongoose does not know ' + 
                        'how to remove an EmbeddedDocument that has no _id');
      }
      this.__parentArray.pull({ _id: _id });
      this.willRemove = true;
    }
  
    if (fn)
      fn(null);
  
    return this;
  };
  
  /**
   * Override #update method of parent documents.
   * @api private
   */
  
  EmbeddedDocument.prototype.update = function () {
    throw new Error('The #update method is not available on EmbeddedDocuments');
  }
  
  /**
   * Helper for console.log
   *
   * @api public
   */
  
  EmbeddedDocument.prototype.inspect = function () {
    return inspect(this.toObject());
  };
  
  /**
   * Marks a path as invalid, causing validation to fail.
   *
   * @param {String} path the field to invalidate
   * @param {String|Error} err error which states the reason `path` was invalid
   * @return {Boolean}
   * @api public
   */
  
  EmbeddedDocument.prototype.invalidate = function (path, err, first) {
    if (!this.__parent) return false;
    var index = this.__parentArray.indexOf(this);
    var parentPath = this.__parentArray._path;
    var fullPath = [parentPath, index, path].join('.');
    this.__parent.invalidate(fullPath, err);
    if (first)
      this._validationError = ownerDocument(this)._validationError;
    return true;
  }
  
  /**
   * Returns the top level document of this sub-document.
   *
   * @return {Document}
   */
  
  EmbeddedDocument.prototype.ownerDocument = function () {
    return ownerDocument(this);
  }
  
  /*!
   * Returns the top level document of this sub-document.
   *
   * @return {Document}
   */
  
  function ownerDocument (self) {
    var parent = self.__parent;
    while (parent.__parent)
      parent = parent.__parent;
    return parent;
  }
  
  /**
   * Returns this sub-documents parent document.
   *
   * @api public
   */
  
  EmbeddedDocument.prototype.parent = function () {
    return this.__parent;
  }
  
  /**
   * Returns this sub-documents parent array.
   *
   * @api public
   */
  
  EmbeddedDocument.prototype.parentArray = function () {
    return this.__parentArray;
  }
  
  /*!
   * Module exports.
   */
  
  module.exports = EmbeddedDocument;
  