/*
Script: Class.Extras.js
Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.

License:
MIT-style license.
*/

var Chain = new Class({

chain: function(){
this.$chain = (this.$chain || []).extend(arguments);
return this;
},

callChain: function(){
return (this.$chain && this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
},

clearChain: function(){
if (this.$chain) this.$chain.empty();
return this;
}

});

var Events = new Class({

addEvent: function(type, fn, internal){
type = Events.removeOn(type);
if (fn != $empty){
this.$events = this.$events || {};
this.$events[type] = this.$events[type] || [];
this.$events[type].include(fn);
if (internal) fn.internal = true;
}
return this;
},

addEvents: function(events){
for (var type in events) this.addEvent(type, events[type]);
return this;
},

fireEvent: function(type, args, delay){
type = Events.removeOn(type);
if (!this.$events || !this.$events[type]) return this;
this.$events[type].each(function(fn){
fn.create({'bind': this, 'delay': delay, 'arguments': args})();
}, this);
return this;
},

removeEvent: function(type, fn){
type = Events.removeOn(type);
if (!this.$events || !this.$events[type]) return this;
if (!fn.internal) this.$events[type].erase(fn);
return this;
},

removeEvents: function(type){
for (var e in this.$events){
if (type && type != e) continue;
var fns = this.$events[e];
for (var i = fns.length; i--; i) this.removeEvent(e, fns[i]);
}
return this;
}

});

Events.removeOn = function(string){
return string.replace(/^on([A-Z])/, function(full, first) {
return first.toLowerCase();
});
};

var Options = new Class({

setOptions: function(){
this.options = $merge.run([this.options].extend(arguments));
if (!this.addEvent) return this;
for (var option in this.options){
if ($type(this.options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
this.addEvent(option, this.options[option]);
delete this.options[option];
}
return this;
}

});