using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using Random = C5.C5Random;

[Serializable]
public class PoolManager : MonoBehaviour
{
	private static readonly string PoolKeyKey = "PoolManager_PoolKey";

	public ObjectPoolInstance[] pools;
	
	private Dictionary<string, ObjectPool> table = new Dictionary<string, ObjectPool> ();
	
	// Local function variable initialized once for optimization
	private List<string> availablePoolsHelper = new List<string> (20);

	private Transform poolsContainer;

	void Awake ()
	{
		var poolsContainerGO = new GameObject ();
		poolsContainerGO.name = "Pools";
		poolsContainerGO.transform.parent = this.transform;
		this.poolsContainer = poolsContainerGO.transform;

		for (int i = 0; i < this.pools.Length; i++) {
			var opi = this.pools [i];
			if (opi.autoInitialize == true) {
				if (opi.pool.poolContainer == null) {
					var curPoolContainerGO = new GameObject ();
					curPoolContainerGO.name = opi.key;
					curPoolContainerGO.transform.parent = this.poolsContainer;
					opi.pool.poolContainer = curPoolContainerGO.transform;
				}
				opi.pool.Initialize ();
			}
			this.table [opi.key] = opi.pool;
		}
	}

	public ObjectPool GetPool (string key)
	{
		return this.table [key];
	}

	public GameObject GetFromPool (string key)
	{
		var result = this.table [key].GetFromPool ();
		result.SetAttachedValue (PoolManager.PoolKeyKey, key);
		return result;
	}

	public GameObject GetFromPool (string key, Vector3 position, Quaternion rotation)
	{
		var result = this.table [key].GetFromPool (position, rotation);
		result.SetAttachedValue (PoolManager.PoolKeyKey, key);
		return result;
	}

	public GameObject GetFromRandomPool (string[] keys, Random r)
	{
		this.InitAvailablePoolsHelper (keys);
		
		GameObject result = null;
		if (this.availablePoolsHelper.Count > 0) {
			var key = this.availablePoolsHelper [r.Next (this.availablePoolsHelper.Count)];
			result = this.table [key].GetFromPool ();
			result.SetAttachedValue (PoolManager.PoolKeyKey, key);
		}
		return result;
	}

	public GameObject GetFromRandomPool (string[] keys, Vector3 position, Quaternion rotation, Random r)
	{
		this.InitAvailablePoolsHelper (keys);
		
		GameObject result = null;
		if (this.availablePoolsHelper.Count > 0) {
			var key = this.availablePoolsHelper [r.Next (this.availablePoolsHelper.Count)];
			result = this.table [key].GetFromPool (position, rotation);
			result.SetAttachedValue (PoolManager.PoolKeyKey, key);
		}
		return result;
	}

	private void InitAvailablePoolsHelper (string[] keys)
	{
		this.availablePoolsHelper.Clear ();
		for (int i = 0; i < keys.Length; i++) {
			var key = keys [i];
			var pool = this.table [key];
			if (pool.remainingObjectsCount > 0) {
				this.availablePoolsHelper.Add (key);
			}
		}
		
		if (this.availablePoolsHelper.Count == 0) {
			for (int i = 0; i < keys.Length; i++) {
				var key = keys [i];
				var pool = this.table [key];
				if (pool.expandIfNeeded == true) {
					this.availablePoolsHelper.Add (key);
				}
			}
		}
	}

	public void ReturnToPool (GameObject poolObject)
	{
		var key = (string)poolObject.GetAttachedValue (PoolManager.PoolKeyKey);
		this.table [key].ReturnToPool (poolObject);
	}

	[Serializable]
	public class ObjectPoolInstance
	{
		public string key;
		public bool autoInitialize = true;
		public ObjectPool pool;
	}
}
