/*
Script: Hash.js
Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects.

License:
MIT-style license.
*/

Hash.implement({

has: Object.prototype.hasOwnProperty,

keyOf: function(value){
for (var key in this){
if (this.hasOwnProperty(key) && this[key] === value) return key;
}
return null;
},

hasValue: function(value){
return (Hash.keyOf(this, value) !== null);
},

extend: function(properties){
Hash.each(properties, function(value, key){
Hash.set(this, key, value);
}, this);
return this;
},

combine: function(properties){
Hash.each(properties, function(value, key){
Hash.include(this, key, value);
}, this);
return this;
},

erase: function(key){
if (this.hasOwnProperty(key)) delete this[key];
return this;
},

get: function(key){
return (this.hasOwnProperty(key)) ? this[key] : null;
},

set: function(key, value){
if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
return this;
},

empty: function(){
Hash.each(this, function(value, key){
delete this[key];
}, this);
return this;
},

include: function(key, value){
var k = this[key];
if (k == undefined) this[key] = value;
return this;
},

map: function(fn, bind){
var results = new Hash;
Hash.each(this, function(value, key){
results.set(key, fn.call(bind, value, key, this));
}, this);
return results;
},

filter: function(fn, bind){
var results = new Hash;
Hash.each(this, function(value, key){
if (fn.call(bind, value, key, this)) results.set(key, value);
}, this);
return results;
},

every: function(fn, bind){
for (var key in this){
if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;
}
return true;
},

some: function(fn, bind){
for (var key in this){
if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true;
}
return false;
},

getKeys: function(){
var keys = [];
Hash.each(this, function(value, key){
keys.push(key);
});
return keys;
},

getValues: function(){
var values = [];
Hash.each(this, function(value){
values.push(value);
});
return values;
},

toQueryString: function(base){
var queryString = [];
Hash.each(this, function(value, key){
if (base) key = base + '[' + key + ']';
var result;
switch ($type(value)){
case 'object': result = Hash.toQueryString(value, key); break;
case 'array':
var qs = {};
value.each(function(val, i){
qs[i] = val;
});
result = Hash.toQueryString(qs, key);
break;
default: result = key + '=' + encodeURIComponent(value);
}
if (value != undefined) queryString.push(result);
});

return queryString.join('&');
}

});

Hash.alias({keyOf: 'indexOf', hasValue: 'contains'});