text: // Generated by CoffeeScript 1.8.0
  var Collection, GearJson, Item, VERSION, defaultTypesMap, each, extend, getType, getset, isArray, objectStr, toString, typesA2O, typesO2A, undefinedStr;
  
  VERSION = 'developing';
  
  undefinedStr = 'undefined';
  
  objectStr = 'object';
  
  toString = Object.prototype.toString;
  
  isArray = Array.isArray;
  
  defaultTypesMap = {
    buffer: {
      type: 'blob',
      cbUnwrap: function(v) {
        return new Buffer(v);
      }
    },
    date: {
      type: 'date',
      cbUnwrap: function(v) {
        return new Date(v);
      }
    }
  };
  
  getType = function(object) {
    var type;
    type = typeof object;
    if (type === undefinedStr) {
      return undefinedStr;
    }
    type = object ? object.constructor.name : toString.call(object).slice(8, -1);
    return type.toLowerCase();
  };
  
  getset = function(obj, path, cb) {
    var last, stopped;
    stopped = false;
    last = path.length - 1;
    return path.reduce((function(obj, key, idx) {
      if (stopped) {
        return;
      }
      if (idx === last) {
        return obj[key] = cb(obj[key]);
      } else {
        if (!obj.hasOwnProperty(key)) {
          return stopped = true;
        }
        return obj[key];
      }
    }), obj);
  };
  
  each = function(obj, cb) {
    var key, value, _i, _j, _len, _len1, _ref;
    if (isArray(obj)) {
      for (key = _i = 0, _len = obj.length; _i < _len; key = ++_i) {
        value = obj[key];
        cb(key, value);
      }
    } else {
      _ref = Object.keys(obj);
      for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
        key = _ref[_j];
        cb(key, obj[key]);
      }
    }
  };
  
  typesO2A = function(obj) {
    var path, type, _results;
    _results = [];
    for (path in obj) {
      type = obj[path];
      _results.push([path.split('.'), type]);
    }
    return _results;
  };
  
  typesA2O = function(arr, sep) {
    if (sep == null) {
      sep = '.';
    }
    return arr.reduce((function(obj, _arg) {
      var pathArr, type;
      pathArr = _arg[0], type = _arg[1];
      obj[pathArr.join(sep)] = type;
      return obj;
    }), {});
  };
  
  extend = function(objTo, objFrom) {
    var k, _i, _len, _ref;
    if (objectStr === typeof objTo && objectStr === typeof objFrom) {
      _ref = Object.keys(objFrom);
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        k = _ref[_i];
        objTo[k] = objFrom[k];
      }
    }
    return objTo;
  };
  
  GearJson = (function() {
    function GearJson(options) {
      if (options == null) {
        options = {};
      }
      this.typesMap = options.typesMap;
      if (!this.typesMap) {
        this.typesMap = defaultTypesMap;
      }
    }
  
    GearJson.prototype.determineTypes = function(item, pathesSkip) {
      var addKey, path, runner, types;
      if (isArray(pathesSkip)) {
        pathesSkip = pathesSkip.reduce((function(o, key) {
          if (isArray(key)) {
            key = key.join('.');
          }
          o[key] = true;
          return o;
        }), {});
      }
      path = [];
      types = [];
      addKey = function(k, type) {
        var pathArr;
        pathArr = path.concat(k);
        if (!(pathesSkip && pathesSkip[pathArr.join('.')])) {
          return types.push([pathArr, type]);
        }
      };
      runner = (function(_this) {
        return function(obj) {
          return each(obj, function(key, value) {
            var valueType;
            if (objectStr === typeof value) {
              valueType = getType(value);
              if (_this.typesMap[valueType]) {
                return addKey(key, _this.typesMap[valueType].type);
              } else {
                path.push(key);
                runner(value);
                return path.pop();
              }
            }
          });
        };
      })(this);
      runner(item);
      return types;
    };
  
    GearJson.prototype.wrapItem = function(item, options) {
      var pathesSkip, result, types;
      if (options == null) {
        options = {};
      }
      types = options.types, pathesSkip = options.pathesSkip;
      if (!types) {
        types = this.determineTypes(item, pathesSkip);
      }
      result = {
        item: item
      };
      if (types.length) {
        if (options.arrTypes) {
          result.types = types;
        } else {
          result.types = typesA2O(types);
        }
      }
      return result;
    };
  
    GearJson.prototype.wrapCollection = function(items, options) {
      var arrTypes, extItems, itemOpts, result, types;
      if (options == null) {
        options = {};
      }
      types = options.types, extItems = options.extItems, arrTypes = options.arrTypes;
      if (!types || extItems) {
        itemOpts = {
          arrTypes: arrTypes
        };
        if (types) {
          itemOpts.pathesSkip = Object.keys(types);
        }
        items = items.map((function(_this) {
          return function(item) {
            return _this.wrapItem(item, itemOpts);
          };
        })(this));
        extItems = true;
      }
      result = {
        items: items
      };
      if (types) {
        result.types = arrTypes ? typesO2A(types) : types;
      }
      if (extItems) {
        result.extItems = true;
      }
      return result;
    };
  
    GearJson.prototype.unwrapItem = function(item, types) {
      var path, type, _i, _len, _ref;
      if (!isArray(types)) {
        types = typesO2A(types);
      }
      for (_i = 0, _len = types.length; _i < _len; _i++) {
        _ref = types[_i], path = _ref[0], type = _ref[1];
        getset(item, path, this.typesMap[type].cbUnwrap);
      }
      return item;
    };
  
    GearJson.prototype.unwrapCollection = function(_arg) {
      var extItems, items, types;
      items = _arg.items, types = _arg.types, extItems = _arg.extItems;
      if (types) {
        if (extItems) {
          items.forEach((function(_this) {
            return function(item) {
              return _this.unwrapItem(item.item, types);
            };
          })(this));
        } else {
          items.forEach((function(_this) {
            return function(item) {
              return _this.unwrapItem(item, types);
            };
          })(this));
        }
      }
      if (extItems) {
        items.forEach((function(_this) {
          return function(item) {
            return _this.unwrapItem(item.item, item.types);
          };
        })(this));
        items = items.map(function(item) {
          return item.item;
        });
      }
      return items;
    };
  
    GearJson.prototype.Collection = function(items, options) {
      var o;
      o = new Collection(items, options);
      o.gj = this;
      return o;
    };
  
    GearJson.prototype.Item = function(item, options) {
      var o;
      o = new Item(item, options);
      o.gj = this;
      return o;
    };
  
    return GearJson;
  
  })();
  
  Collection = (function() {
    function Collection(items, options) {
      this.items = items;
      this.options = options;
    }
  
    Collection.prototype.wrap = function(options) {
      return this.gj.wrapCollection(this.items, extend(this.options, options));
    };
  
    return Collection;
  
  })();
  
  Item = (function() {
    function Item(item, options) {
      this.item = item;
      this.options = options;
    }
  
    Item.prototype.wrap = function(options) {
      return this.gj.wrapItem(this.item, extend(this.options, options));
    };
  
    return Item;
  
  })();
  
  module.exports = GearJson;
  