//some functional programming functions
function mfMap(functionPointer, someList) {
    var ret = new Array(someList.length);
    for (var i = 0; i < someList.length; i++) {
        ret[i] = functionPointer(someList[i]);
    }
    return ret;
}

function mfFilter(functionPointer, someList) {
    var ret = new Array();
    for (var i = 0; i < someList.length; i++) {
        if (functionPointer(someList[i])) {
            ret.push(someList[i]);
        }
    }
    return ret;
}

function mfObserver(event_types) {
    this.fns_dict = {};
    for (var i = 0; i < event_types.length; i++) {
        this.fns_dict[event_types[i]] = [];
    }
}

mfObserver.prototype = {
    subscribe : function(type, fn) {
        this.fns_dict[type].push(fn);
    },
    unsubscribe : function(type, fn) {
        this.fns_dict[type] = mfFilter(
                function(el) {
                    return ( el != fn );
                },
                this.fns_dict[type]
                );
    },
    fire : function(type, o, thisObj) {
        var scope = thisObj || window;
        var f = function(el) {
            el.call(scope, o);
        };
        if(!this.fns_dict[type]){
            alert("No such type: "+type);
        }
        //debug("[DISPATCHER] Fire "+type+" for "+this.fns_dict[type].length+" subscriber(s).");
        for (var i = 0; i < this.fns_dict[type].length; i++) {
            f(this.fns_dict[type][i]);
        }
    }
};

function mfLoopStorage() {
    this.storage = {};
    this.sequence = 0;
}
mfLoopStorage.prototype = {
    getNew:function() {
        if (Number.MAX_VALUE == this.sequence){
            //hopefully by the time we got here no loops with low ids exist
            this.sequence = 0;
        }
        this.sequence++;
        var s = new String(this.sequence);
        this.storage[s] = true;
        return s;
    },
    exists:function(id) {
        var undef;
        var item = this.storage[id];
        return (!(item == undef));
    },
    remove:function(id) {
        delete this.storage[id];
    },
    reset:function() {
        this.storage = {};
    }
};
