;(function( $ ){

    var _instances = {};

    function Poll( name, configuration ){
    
        _validate( name )
    
        this.name = name;
        
        this.configuration = $.extend({
        
            channel: Chemistry.channels.MASTER,
            
            frequency: 60000
                
        }, configuration || {});
        
                
        _instances[name] = this;
        
    };
    
    Poll.prototype = {

        start: function(){
            
            if (!this.timer) {
            
                this.timer = setInterval($.proxy(this.fetch, this), this.configuration.frequency);
            
            }
        
        },
        
        fetch: function(){
        
            if (this.xhr) { 
                
                return; 
            
            }
        
            this.xhr = $.ajax({

				cache: false,
            
                url: this.configuration.url, 
                
                success: $.proxy(_fetchSuccess, this),
                
                complete: $.proxy(_fetchComplete, this)
                
            });
        
        },
        
        /**
         * Stop a poll and aborts the current poll request if one is being made.
         */
        stop: function(){
        
            this.timer && clearInterval(this.timer);
            			
            this.xhr && this.xhr.abort();
            
			this.timer = null;

			this.xhr = null;

        },
        
        /**
         * Stops a poll and removes the instance pointer from the instances set, but does not delete the instance.
         */
        destroy: function(){
        
            this.stop();
        
            delete _instances[name];

        },
        
        configure: function(key, value){

            typeof key === 'object' ? $.extend(this.configuration, key) : (this.configuration[key] = value);

        },

        /**
         * A restart is required when the frequency of a poll is altered because you can't modify an interval after it's been created.
         */
        restart: function(){
        
            this.stop();
            
            this.start();
                
        },
		
		/**
		 * Is this instance actively polling?
		 * @returns Boolean
		 */
		active: function(){
			
			return !!this.timer;
				
		}
		
    };
    
    function _validate( name ) {
    
        if ( !name || typeof(name) !== 'string'){
            
            $.error("Poll instances must be given a unique name.");
        
        }
        
        if (_instances[name])
        {
            $.error("An instance with the given name already exists. name: " + name); 
        }    
    
    };
    
    function _fetchSuccess( data ){
    
        $.publish(this.configuration.channel, [ data ]);
        
    };
    
    function _fetchComplete( data ){
    
        this.xhr = null;
        
    };
    
    /**
     * Retrieve an instance of a Poll object by name.
     */
    Poll.instance = function( name ){
        
        return _instances[name];
        
    };
    
    /**
     * Calls the stop method on all poll instances.
     */
    Poll.stopAll = function(){
    
        for (var p in _instances){
        
            _instances[p].stop();
        
        }
    
    };
            
    Chemistry.include({ Poll:Poll });

})( jQuery );
