package com.uoc.educationalVG.framework;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 * The getTouchEvents() and getKeyEvents() methods return TouchEvents and
 * KeyEvents lists. In our keyboard and touch event handlers, we constantly
 * create instances of these two classes and store them in lists that are
 * internal to the handlers. The Android input system fires many of these events
 * when a key is pressed or a finger touches the screen, so we constantly create
 * new instances that are collected by the garbage collector in short intervals.
 * In order to avoid this, we implement a concept known as instance pooling.
 * Instead of repeatedly creating new instances of a class, we simply reuse
 * previously-created instances. The Pool class is a convenient way to implement
 * that behavior.
 * 
 * @author "Beginning Android 4 Games Development"
 * 
 * @param <T>
 */

public class Pool<T> {
	/**
	 * An interface called PoolObjectFactory is the first thing defined and is,
	 * once again, generic. It has a single method, createObject() that will
	 * return a new object with the generic type of the Pool/PoolObjectFactory
	 * instance.
	 * 
	 * The Pool class has three members. These include an ArrayList to store
	 * pooled objects, a PoolObjectFactory that is used to generate new
	 * instances of the type held by the class, and a member that stores the
	 * maximum number of objects the Pool can hold. The last bit is needed so
	 * our Pool does not grow indefinitely; otherwise, we might run into an
	 * out-of-memory exception.
	 */
	public interface PoolObjectFactory<T> {
		public T createObject();
	}

	private final List<T> freeObjects;
	private final PoolObjectFactory<T> factory;
	private final int maxSize;

	/**
	 * The constructor of the Pool class takes a PoolObjectFactoryand the
	 * maximum number of objects it should store. We store both parameters in
	 * the respective members and instantiate a new ArrayList with the capacity
	 * set to the maximum number of objects.
	 * 
	 * @param factory
	 * @param maxSize
	 */

	public Pool(PoolObjectFactory<T> factory, int maxSize) {
		this.factory = factory;
		this.maxSize = maxSize;
		this.freeObjects = new ArrayList<T>(maxSize);
	}

	/**
	 * The newObject() method is responsible for either handing us a brand-new
	 * instance of the type held by the Pool, via the
	 * PoolObjectFactory.newObject() method, or it returns a pooled instance in
	 * case there’s one in the freeObjects ArrayList. If we use this method, we
	 * get recycled objects as long as the Pool has some stored in the
	 * freeObjects list. Otherwise, the method creates a new one via the
	 * factory.
	 * 
	 * @return object
	 */

	public T newObject() {
		T object = null;

		if (freeObjects.size() == 0)
			object = factory.createObject();
		else
			object = freeObjects.remove(freeObjects.size() - 1);

		return object;
	}

	/**
	 * The free() method lets us reinsert objects that we no longer use. It
	 * simply inserts the object into the freeObjectslist if it is not yet
	 * filled to capacity. If the list is full, the object is not added, and it
	 * is likely to be consumed by the garbage collector the next time it
	 * executes.
	 * 
	 * @param object
	 */

	public void free(T object) {
		if (freeObjects.size() < maxSize)
			freeObjects.add(object);
	}
}
