package com.appdivision.business.httppoller
{
    import flash.events.TimerEvent;
    import flash.utils.Dictionary;
    import flash.utils.Timer;
    
    import mx.rpc.IResponder;
    /**
     * Static class to manage polling services within an application
     * @author ecancil
     * 
     */    
    public class HttpPoller
    {
        
        private static const dict:Dictionary = new Dictionary(true);
        private static const timerMap:Dictionary = new Dictionary(true);
        
        /**
         * Handles all timer events and delegates to the correct poll
         * @param e
         * 
         */        
        private static function onTimer(e:TimerEvent):void{
            var infoObject:Object = timerMap[e.currentTarget];
            if(!infoObject)return;
            doServiceCall(infoObject);
        }
        
        /**
         * Removing service call logic into its own method so it can be called independently of a timer
         * @param infoObject
         * 
         */        
        private static function doServiceCall(infoObject:Object):void{
            var delegate:Object = infoObject['delegate']
            delegate[infoObject['method']].apply(delegate, infoObject['arguments']);
        }
        
        /**
         *Adds http polling mechanism and starts the process of managing it 
         * @param id - id with which to lookup poll in the future
         * @param timeout - time between each poll
         * @param clazz - delegate class to call to run the poll
         * @param method - method on the class to call
         * @param arguments - arguments to pass to method
         * @param responder - class that implements IResponder to return the service too, this is passed to the constructor of the 'clazz' variable
         * @param callImmediately - boolean value specifying whether to call the service immediately
         * @param autoStart - boolean value specifying whether to auto start the service, if this is set to false you can manually call the startByID method
         * 
         */        
        public static function addHTTPPoll(id:Object, timeout:Number, clazz:Class, method:String, arguments:Array, responder:IResponder, callImmediately:Boolean = true, autoStart:Boolean = true):void{
            var infoObject:Object = new Object();
            infoObject['delegate'] = new clazz(responder);
            infoObject['timeout'] = timeout;
            infoObject['method'] = method;
            infoObject['arguments'] = arguments;
            infoObject['responder'] = responder;
            infoObject['timer'] = new Timer(timeout);
            Timer(infoObject['timer']).addEventListener(TimerEvent.TIMER, onTimer);
            
            dict[id] = infoObject;
            timerMap[infoObject['timer']] = dict[id];
            
            if(callImmediately)doServiceCall(infoObject);
            if(autoStart)startByID(id);
        }
        
        /**
         *removes an http poll and cleans up 
         * @param id - id with which to look up the poll
         * 
         */        
        public static function removeHTTPPoll(id:Object):void{
            var infoObject:Object = dict[id];
            if(!infoObject)throw new Error('There is no HTTP service by this ID');
            var timer:Timer = Timer(infoObject['timer']);
            timer.stop();
            timerMap[timer] = null;
            infoObject['timer'] = null;
            dict[infoObject] = null;
        }
        
        /**
         * starts an existing http poll
         * @param id - id with which to look up the poll
         * 
         */        
        public static function startByID(id:Object):void{
            var infoObject:Object = dict[id];
            if(!infoObject)throw new Error('There is no HTTP service by this ID');
            var timer:Timer = Timer(infoObject['timer']);
            timer.delay = infoObject['timeout'];
            timer.start();
        }
        
        /**
         * pauses an existing http poll
         * @param id - id with which to look up the poll
         * 
         */        
        public static function pauseByID(id:Object):void{
            var infoObject:Object = dict[id];
            if(!infoObject)return;
            var timer:Timer = Timer(infoObject['timer']);
            if(timer.running)timer.stop();
            
        }
        
        /**
         *Pauses all existing http polls 
         * 
         */        
        public static function pauseAll():void{
            for each(var infoObject:Object in dict){
                var timer:Timer = Timer(infoObject['timer']);
                if(timer.running)timer.stop();
            }
        }
        
        /**
         *Starts all existing http polls 
         * 
         */        
        public static function startAll():void{
            for each(var infoObject:Object in dict){
                var timer:Timer = Timer(infoObject['timer']);
                if(!timer.running)timer.start();
            }
        }
        
        /**
         * adjusts timeout on an existing http poll
         * @param id - id with which to look up the poll
         * @param timeout - new timeout value
         * 
         */        
        public static function adjustTimeoutByID(id:Object, timeout:Number):void{
            var infoObject:Object = dict[id];
            if(!infoObject)return;
            infoObject['timeout'] = timeout;
        }
        
        /**
         * adjusts arguments for an existing http poll
         * @param id - id with which to look up the poll
         * @param arguments - new arguments
         * 
         */                
        public static function adjustArgumentsByID(id:Object, arguments:Array):void{
            var infoObject:Object = dict[id];
            if(!infoObject)return;
            infoObject['arguments'] = arguments;
        }
        
        /**
         * checks if an http poll exists
         * @param id - id with which to look up the poll
         * @return boolea
         * 
         */        
        public static function exists(id:Object):Boolean{
            return dict[id] != null;
        }
    }
}