/*
  Lifecycle.js 1.0.4
  (c) 2011, 2012 Kevin Malakoff - http://kmalakoff.github.com/json-serialize/
  License: MIT (http://www.opensource.org/licenses/mit-license.php)

 Note: some 'extend'-related code from Backbone.js is repeated in this file.
 Please see the following for details on Backbone.js and its licensing:
   https:github.com/documentcloud/backbone/blob/master/LICENSE
*/
(function() {
  return (function(factory) {
    // AMD
    if (typeof define === 'function' && define.amd) {
      return define('lifecycle', factory);
    }
    // CommonJS/NodeJS or No Loader
    else {
      return factory.call(this);
    }
  })(function() {// Generated by CoffeeScript 1.10.0

/*
  Lifecycle.js 1.0.4
  (c) 2011, 2012 Kevin Malakoff - http://kmalakoff.github.com/json-serialize/
  License: MIT (http://www.opensource.org/licenses/mit-license.php)

 Note: some 'extend'-related code from Backbone.js is repeated in this file.
 Please see the following for details on Backbone.js and its licensing:
   https:github.com/documentcloud/backbone/blob/master/LICENSE
 */
var LC, copyProps, isArray;

LC = this.LC = typeof exports !== 'undefined' ? exports : {};

LC.VERSION = "1.0.4";

isArray = function(obj) {
  return obj.constructor === Array;
};

copyProps = function(dest, source) {
  var key, value;
  for (key in source) {
    value = source[key];
    dest[key] = value;
  }
  return dest;
};

// Shared empty constructor function to aid in prototype-chain creation.
var ctor = function(){};

// Helper function to correctly set up the prototype chain, for subclasses.
// Similar to 'goog.inherits', but uses a hash of prototype properties and
// class properties to be extended.
var inherits = function(parent, protoProps, staticProps) {
  var child;

  // The constructor function for the new subclass is either defined by you
  // (the "constructor" property in your extend definition), or defaulted
  // by us to simply call the parent's constructor.
  if (protoProps && protoProps.hasOwnProperty('constructor')) {
    child = protoProps.constructor;
  } else {
    child = function(){ parent.apply(this, arguments); };
  }

  // Inherit class (static) properties from parent.
  copyProps(child, parent);

  // Set the prototype chain to inherit from parent, without calling
  // parent's constructor function.
  ctor.prototype = parent.prototype;
  child.prototype = new ctor();

  // Add prototype properties (instance properties) to the subclass,
  // if supplied.
  if (protoProps) copyProps(child.prototype, protoProps);

  // Add static properties to the constructor function, if supplied.
  if (staticProps) copyProps(child, staticProps);

  // Correctly set child's 'prototype.constructor'.
  child.prototype.constructor = child;

  // Set a convenience property in case the parent's prototype is needed later.
  child.__super__ = parent.prototype;

  return child;
};

// The self-propagating extend function that BacLCone classes use.
var extend = function (protoProps, classProps) {
  var child = inherits(this, protoProps, classProps);
  child.extend = this.extend;
  return child;
};
;

LC.own = function(obj, options) {
  var clone, i, j, key, len, len1, value;
  if (!obj || (typeof obj !== "object")) {
    return obj;
  }
  options || (options = {});
  if (isArray(obj)) {
    if (options.share_collection) {
      for (i = 0, len = obj.length; i < len; i++) {
        value = obj[i];
        LC.own(value, {
          prefer_clone: options.prefer_clone
        });
      }
      return obj;
    } else {
      clone = [];
      for (j = 0, len1 = obj.length; j < len1; j++) {
        value = obj[j];
        clone.push(LC.own(value, {
          prefer_clone: options.prefer_clone
        }));
      }
      return clone;
    }
  } else if (options.properties) {
    if (options.share_collection) {
      for (key in obj) {
        value = obj[key];
        LC.own(value, {
          prefer_clone: options.prefer_clone
        });
      }
      return obj;
    } else {
      clone = {};
      for (key in obj) {
        value = obj[key];
        clone[key] = LC.own(value, {
          prefer_clone: options.prefer_clone
        });
      }
      return clone;
    }
  } else if (obj.retain) {
    if (options.prefer_clone && obj.clone) {
      return obj.clone();
    } else {
      return obj.retain();
    }
  } else if (obj.clone) {
    return obj.clone();
  }
  return obj;
};

LC.disown = function(obj, options) {
  var i, index, key, len, value;
  if (options == null) {
    options = {};
  }
  if (!obj || (typeof obj !== "object")) {
    return obj;
  }
  if (isArray(obj)) {
    if (options.clear_values) {
      for (index in obj) {
        value = obj[index];
        LC.disown(value, {
          clear_values: options.clear_values
        });
        obj[index] = null;
      }
    } else {
      for (i = 0, len = obj.length; i < len; i++) {
        value = obj[i];
        LC.disown(value, {
          remove_values: options.remove_values
        });
      }
      if (options.remove_values) {
        obj.length = 0;
      }
    }
  } else if (options.properties) {
    if (options.clear_values) {
      for (key in obj) {
        value = obj[key];
        LC.disown(value, {
          clear_values: options.clear_values
        });
        obj[key] = null;
      }
    } else {
      for (key in obj) {
        value = obj[key];
        LC.disown(value, {
          remove_values: options.remove_values
        });
        delete obj[key];
      }
    }
  } else if (obj.release) {
    obj.release();
  } else if (obj.destroy) {
    obj.destroy();
  }
  return obj;
};

LC.RefCountable = (function() {
  RefCountable.extend = extend;

  function RefCountable() {
    this.__LC || (this.__LC = {});
    this.__LC.ref_count = 1;
  }

  RefCountable.prototype.__destroy = function() {};

  RefCountable.prototype.retain = function() {
    if (this.__LC.ref_count <= 0) {
      throw "RefCountable: ref_count is corrupt: " + this.__LC.ref_count;
    }
    this.__LC.ref_count++;
    return this;
  };

  RefCountable.prototype.release = function() {
    if (this.__LC.ref_count <= 0) {
      throw "RefCountable: ref_count is corrupt: " + this.__LC.ref_count;
    }
    this.__LC.ref_count--;
    if (!this.__LC.ref_count) {
      this.__destroy();
    }
    return this;
  };

  RefCountable.prototype.refCount = function() {
    return this.__LC.ref_count;
  };

  return RefCountable;

})();
; return LC;});
}).call(this);