<?php /* EL PSY CONGROO */     			  		
      		  		
namespace Guzzle\Batch;        	 		
    	   				
use Guzzle\Batch\Exception\BatchTransferException;     		 	 		
    	  	 		 
/**     	 		 	 
 * Default batch implementation used to convert queued items into smaller chunks of batches using a      					 
 * {@see BatchDivisorIterface} and transfers each batch using a {@see BatchTransferInterface}.    		  				
 *    							 
 * Any exception encountered during a flush operation will throw a {@see BatchTransferException} object containing the      	 		 	
 * batch that failed. After an exception is encountered, you can flush the batch again to attempt to finish transferring    	 		 	 	
 * any previously created batches or queued items.     		    	
 */            
class Batch implements BatchInterface    			 	   
{    	 			  	
    /** @var \SplQueue Queue of items in the queue */      		    
    protected $queue;      				 	
     	 				 
    /** @var array Divided batches to be transferred */    	    			
    protected $dividedBatches;     				   
       	  		
    /** @var BatchTransferInterface */     	 		  	
    protected $transferStrategy;     		 	   
    	  	 	  
    /** @var BatchDivisorInterface */     	  	 		
    protected $divisionStrategy;    	 		 	 	
       		  	
    /**    		 		 		
     * @param BatchTransferInterface $transferStrategy Strategy used to transfer items     	 		 		
     * @param BatchDivisorInterface  $divisionStrategy Divisor used to create batches    	 	 		 	
     */     				   
    public function __construct(BatchTransferInterface $transferStrategy, BatchDivisorInterface $divisionStrategy)    	 	    	
    {    	 				 	
        $this->transferStrategy = $transferStrategy;     	 		  	
        $this->divisionStrategy = $divisionStrategy;      	 		 	
        $this->queue = new \SplQueue();       				 
        $this->queue->setIteratorMode(\SplQueue::IT_MODE_DELETE);     	 	    
        $this->dividedBatches = array();      		  		
    }    	 			 	 
      			   
    public function add($item)     		 		 	
    {     		 	   
        $this->queue->enqueue($item);     				  	
    	  			  
        return $this;    			   		
    }    	 	 	   
     					 	
    public function flush()    	  		  	
    {     			  		
        $this->createBatches();    					 	 
    	  		 	 
        $items = array();     	 	 	  
        foreach ($this->dividedBatches as $batchIndex => $dividedBatch) {     		 	 	 
            while ($dividedBatch->valid()) {    		 	  	 
                $batch = $dividedBatch->current();    	  		 		
                $dividedBatch->next();    	 			   
                try {         		 
                    $this->transferStrategy->transfer($batch);    				   	
                    $items = array_merge($items, $batch);    	   	 		
                } catch (\Exception $e) {    		  		  
                    throw new BatchTransferException($batch, $items, $e, $this->transferStrategy, $this->divisionStrategy);     		  	 	
                }     	  	 	 
            }    		 			 	
            // Keep the divided batch down to a minimum in case of a later exception    					   
            unset($this->dividedBatches[$batchIndex]);         	 	
        }    		   	 	
     	 					
        return $items;     	 		 		
    }    	 			   
    		 					
    public function isEmpty()    	   	  	
    {    	   		  
        return count($this->queue) == 0 && count($this->dividedBatches) == 0;     		 	 	 
    }    			  		 
    	  	 			
    /**      	    	
     * Create batches for any queued items    		 	 	 	
     */    	   	 	 
    protected function createBatches()    	  	   	
    {     	 		 	 
        if (count($this->queue)) {      						
            if ($batches = $this->divisionStrategy->createBatches($this->queue)) {    			  	 	
                // Convert arrays into iterators    	  	 		 
                if (is_array($batches)) {    	  	    
                    $batches = new \ArrayIterator($batches);      	 	 	 
                }     	  				
                $this->dividedBatches[] = $batches;    			   		
            }    	 	   		
        }    		     	
    }    		 	 	  
}        		 	
    			 				