(function() {
  var __hasProp = Object.prototype.hasOwnProperty, __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (__hasProp.call(this, i) && this[i] === item) return i; } return -1; };

  this.def_class('Rome',DObject,function(__scope,__class){

    if(!this.__ctor__){this.__ctor__= function Rome(){}; this.__ctor__.prototype = this.prototype; }

    this.def_class('Types',DObject,function(__scope,__class){

      if(!this.__ctor__){this.__ctor__= function Types(){}; this.__ctor__.prototype = this.prototype; }

      this.def_class('Base',DObject,function(__scope,__class){

        this.property = function(klass, key, options) {
          return new (__ctor(this))(klass, key, options);
        };__singleton_method_added(this,"property");

        this.__ctor__ = function Base(klass, key, options) {
          this["@klass"] = klass;
          this["@key"] = key;
          this["@options"] = options;
          return this;
        }; this.__ctor__.prototype = this.prototype;;

        this.prototype.get = function(doc, key) {
          return doc["@attributes"][key] || this.default(doc, key);
        }; __method_added(this,"get");

        this.prototype.set = function(doc, key, value) {
          var old;
          old = this.get(doc, key);
          value = this.normalize(value);
          if (value !== old) {
            doc["@attributes"][key] = value;
            doc["@dirty"].sadd(key);
            doc.emit('change:' + key, value, old);
          }
          return value;
        }; __method_added(this,"set");

        this.prototype.load = function(doc, key, value) {
          return doc["@attributes"][key] = this.normalize(value);
        }; __method_added(this,"load");

        this.prototype.normalize = function(value) {
          return value;
        }; __method_added(this,"normalize");

        this.prototype.validate = function(value) {
          return true;
        }; __method_added(this,"validate");

        this.prototype.default = function() {
          return null;
        }; __method_added(this,"default");

      });

      this.def_class('String',__scope.Base,function(__scope,__class){

        if(!this.__ctor__){this.__ctor__= function String(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

        this.prototype.normalize = function(value) {
          if (typeof value === 'string') {
            return value;
          } else if (typeof value === 'number') {
            return "" + value;
          } else {
            return nil;
          }
        }; __method_added(this,"normalize");

        this.prototype.default = function() {
          return "";
        }; __method_added(this,"default");

      });

      this.def_class('Number',__scope.Base,function(__scope,__class){

        if(!this.__ctor__){this.__ctor__= function Number(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

        this.prototype.normalize = function(value) {
          if (typeof value === 'string') {
            return parseFloat(value);
          } else if (typeof value === 'boolean') {
            return value && 1 || 0;
          } else if (typeof value === 'number') {
            return value;
          } else {
            return nil;
          }
        }; __method_added(this,"normalize");

        this.prototype.default = function() {
          return 0;
        }; __method_added(this,"default");

      });

      this.def_class('Bool',__scope.Base,function(__scope,__class){

        if(!this.__ctor__){this.__ctor__= function Bool(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

        this.prototype.normalize = function(value) {
          return !!value;
        }; __method_added(this,"normalize");

        this.prototype.default = function() {
          return false;
        }; __method_added(this,"default");

      });

      this.def_class('Struct',__scope.Base,function(__scope,__class){

        if(!this.__ctor__){this.__ctor__= function Struct(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

        this.prototype.get = function(doc, key) {
          var _name;
          return doc[_name = "@" + key] || (doc[_name] = new (__ctor(this.type()))(doc, key, this["@options"]));
        }; __method_added(this,"get");

        this.prototype.set = function(doc, key, value) {
          throw 'cannot set struct-property directly on doc';
        }; __method_added(this,"set");

        this.prototype.load = function(doc, key, data) {
          return this.get(doc, key).load(data);
        }; __method_added(this,"load");

      });

      this.def_class('List',__scope.Struct,function(__scope,__class){

        if(!this.__ctor__){this.__ctor__= function List(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

        this.prototype.type = function() {
          return __scope.Rome.List;
        }; __method_added(this,"type");

      });

      this.def_class('Bitmap',__scope.Struct,function(__scope,__class){

        if(!this.__ctor__){this.__ctor__= function Bitmap(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

        this.prototype.type = function() {
          return __scope.Rome.Bitmap;
        }; __method_added(this,"type");

      });

      this.def_class('Hash',__scope.Struct,function(__scope,__class){

        if(!this.__ctor__){this.__ctor__= function Hash(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

        this.prototype.type = function() {
          return __scope.Rome.Hash;
        }; __method_added(this,"type");

      });

    });

    this.def_class('Document',__scope.Struct,function(__scope,__class){

      this.key = function(key, typename, options) {
        var prop, properties, proto, type;
        if (options == null) options = {};
        type = __scope.Rome.Types[typename.camelcase()];
        proto = this['prototype'];
        properties = proto["@properties"] || (proto["@properties"] = {});
        prop = properties[key] = type.property(this, key, options);
        proto[key] = function() {
          return this["@properties"][key].get(this, key);
        };
        proto[key + "="] = function(val) {
          return this["@properties"][key].set(this, key, val);
        };
        return true;
      };__singleton_method_added(this,"key");

      this.get = function(id, block) {
        var doc;
        if (doc = this.repository()["cached?"](this, id)) {
          if (block) doc.onready(block);
          return doc;
        } else {
          return new (__ctor(this))({
            _id: id
          }, block);
        }
      };__singleton_method_added(this,"get");

      this.create = function(attributes, cb) {
        var doc;
        doc = new (__ctor(this))(attributes);
        doc.save(cb);
        return doc;
      };__singleton_method_added(this,"create");

      this.__ctor__ = function Document(attributes, onready) {
        var key, prop, _ref;
        if (attributes == null) attributes = {};
        this["@attributes"] = attributes;
        this["@dirty"] = [];
        if (this.id()) {
          this.repository().cache(this);
          this.fetch(onready);
        } else {
          _ref = this["@properties"];
          for (key in _ref) {
            prop = _ref[key];
            prop.load(this, key, this["@attributes"][key]);
          }
        }
        return this;
      }; this.__ctor__.prototype = this.prototype;;

      this.prototype.attributes = function() {
        return this["@attributes"];
      }; __method_added(this,"attributes");

      this.prototype.id = function() {
        return this["@attributes"]['_id'];
      }; __method_added(this,"id");

      this.prototype["id="] = function(id) {
        this["@attributes"]['_id'] = id;
        return this.repository().cache(this);
      }; __method_added(this,"id=");

      this.prototype.ns = function() {
        return this.class().name().pluralize().downcase();
      }; __method_added(this,"ns");

      this.prototype.fetch = function(cb) {
        var _this = this;
        return this.repository().fetch(this, function(err, data) {
          _this.refresh(data);
          return cb && cb.call(_this, _this);
        });
      }; __method_added(this,"fetch");

      this.prototype.save = function(cb) {
        return (this["new?"]() ? this["create!"](cb) : this["update!"](cb));
      }; __method_added(this,"save");

      this.prototype["create!"] = function(cb) {
        var _this = this;
        this.repository().save(this, function(err, data) {
          _this.refresh(data);
          cb && cb.call(_this, _this);
          return _this["ready!"]();
        });
        return this;
      }; __method_added(this,"create!");

      this.prototype["update!"] = function(cb) {
        var _this = this;
        if (!this["dirty?"]()) return this;
        this.repository().save(this, function(err, data) {
          _this.refresh(data);
          cb && cb.call(_this, _this);
          return _this["ready!"]();
        });
        return this;
      }; __method_added(this,"update!");

      this.prototype["destroy!"] = function(cb) {
        var _this = this;
        return this.repository().destroy(this, function(err, data) {
          _this["destroyed!"]();          return cb && cb.call(_this, _this);
        });
      }; __method_added(this,"destroy!");

      this.prototype.refresh = function(attributes) {
        var k, prop, v;
        for (k in attributes) {
          if (!__hasProp.call(attributes, k)) continue;
          v = attributes[k];
          if (prop = this["@properties"][k]) {
            prop.load(this, k, v);
          } else {
            true;
          }
        }
        this["ready!"]();
        return true;
      }; __method_added(this,"refresh");

      this.prototype["state="] = function(state) {
        return this["@state"] = state;
      }; __method_added(this,"state=");

      this.prototype["ready?"] = function() {
        return __indexOf.call($READY, this["@state"]) >= 0;
      }; __method_added(this,"ready?");

      this.prototype["ready!"] = function() {
        var _this = this;
        this["@state"] = $READY_CLEAN;
        this["@onready"] && this["@onready"].each(function() {
          return arguments[0](_this);
        });
        this["@onready"] = nil;
        return this;
      }; __method_added(this,"ready!");

      this.prototype["destroyed!"] = function() {
        this["state="]($DESTROYED);
        this.emit('destroy', this);
        return this;
      }; __method_added(this,"destroyed!");

      this.prototype.onready = function(blk) {
        if (this["ready?"]()) return blk(this);
        this["@onready"] || (this["@onready"] = []);
        this["@onready"].push(blk);
        return this;
      }; __method_added(this,"onready");

      this.prototype["dirty?"] = function() {
        return this["@dirty"]["any?"]();
      }; __method_added(this,"dirty?");

      this.prototype.changes = function() {
        var changes;
        var _this = this;
        changes = {};
        this["@dirty"].each(function(key) {
          var val;
          val = _this[key]();
          return changes[key] = val.flush ? val.flush() : val;
        });
        return changes;
      }; __method_added(this,"changes");

      this.prototype["new?"] = function() {
        return !this.id();
      }; __method_added(this,"new?");

    });

  });

}).call($$base);

