/**
 * meltmedia Prototype Custom Event
 * A static event handler for custom object events
 * @version 1.0.0
 * @author Nick Crohn nick@meltmedia.com
 */

/** @class */
meltmedia.CustomEvent = {
    // @ignore
    Version: "1.0.0",

    /**
     * Fire method which takes in an event to fire and a response from the method firing this event.
     * @param {String} eventName Name of the event
     * @param {Mixed} response Any value that is passed from the method firing the event.
     */
    fire: function(eventName, response) {
        if(this.events && this.events[eventName]) {
            for(var i=0;i<this.events[eventName].listeners.length;i++) {
                if(!this.events[eventName].listeners[i].stopped) {
                    try {
                        this.events[eventName].listeners[i].callback({
                                type: eventName,
                                response: response,
                                toString: function() {
                                    return "[object CustomEvent]";
                                }
                            });
                    } catch (e) {
                        //console.error("CustomEvent ["+eventName+":"+this.events[eventName].listeners[i].callback.toString().split("{")[0]+"]: "+e.message);
                        throw new Error(e.message);
                    }
                }
            }
        }
    },

    /**
     * Observe method which registers a method with an event in the events object
     * @param {String} eventName Name of the event that is being observed
     * @param {Function} callback Method which will be executed when the event is fired
     */
    observe: function(eventName, callback) {
        if(!this.events) this.events = {};
        if(this.events[eventName]) {
            this.events[eventName].listeners.push({callback: callback, stopped: false});
        } else {
            this.events[eventName] = {
                listeners: [ {callback: callback, stopped: false} ]
            };
        }
    },
    
    /**
     * Stop method which prevents a specific event from being fired.
     * @param {String} eventName Name of the event
     * @param {Function} callback Method that was originally observed
     */
    stop: function(eventName, callback) {
        if(this.events) {
            for(var i=0;i<this.events[eventName].listeners.length;i++) {
                if(callback) {
                    if(this.events[eventName].listeners[i].callback.toString() == callback.toString()) {
                        this.events[eventName].listeners[i].stopped = true;
                    }
                } else {
                    this.events[eventName].listeners[i].stopped = true;
                }
            }
        }
    },

    /**
     * Start method which enables an event to be fired again after being stopped.
     * @param {String} eventName Name of the event
     * @param {Function} callback Method that was originally observed
     */
    start: function(eventName, callback) {
        if(this.events) {
            for(var i=0;i<this.events[eventName].listeners.length;i++) {
                if(callback) {
                    if(this.events[eventName].listeners[i].callback == callback) {
                        this.events[eventName].listeners[i].stopped = false;
                    }
                } else {
                    this.events[eventName].listeners[i].stopped = false;
                }
            }
        }
    },

    hasObserver: function(eventName) {
        if(this.events) {
            if(this.events[eventName]) return true;
            return false;
        }
    }
};

