namespace Guru
{
    using UnityEngine;
	using System.Collections.Generic;
	using System;
	using System.Threading;
	using System.Linq;

	public class Loom : MonoBehaviour
	{
		public static int maxThreads = 8;
		static int numThreads;

		private static Loom _current;
		private int _count;
		public static Loom Current
		{
			get
			{
				Initialize();
				return _current;
			}
		}

		void Awake()
		{
			_current = this;
			initialized = true;
		}

		static bool initialized;

		static void Initialize()
		{
			if (!initialized)
			{
				if (!Application.isPlaying)
					return;
				
				initialized = true;
				var g = new GameObject("Loom");
				_current = g.AddComponent<Loom>();
				DontDestroyOnLoad(g); // 增加GO持久化
			}

		}

		private List<Action> _actions = new List<Action>();
		public struct DelayedQueueItem
		{
			public float time;
			public Action action;
		}
		private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();

		List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();

		public static void QueueOnMainThread(Action action)
		{
			QueueOnMainThread(action, 0f);
		}
		public static void QueueOnMainThread(Action action, float time)
		{
			if (time != 0)
			{
				lock (Current._delayed)
				{
					Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
				}
			}
			else
			{
				lock (Current._actions)
				{
					Current._actions.Add(action);
				}
			}
		}

		public static Thread RunAsync(Action a)
		{
			Initialize();
			while (numThreads >= maxThreads)
			{
				Thread.Sleep(1);
			}
			Interlocked.Increment(ref numThreads);
			ThreadPool.QueueUserWorkItem(RunAction, a);
			return null;
		}

		private static void RunAction(object action)
		{
			try
			{
				((Action)action)();
			}
			catch
			{
			}
			finally
			{
				Interlocked.Decrement(ref numThreads);
			}
		}

		void OnDisable()
		{
			if (_current == this)
			{

				_current = null;
			}
		}

		List<Action> _currentActions = new List<Action>();

		// Update is called once per frame
		void Update()
		{
			lock (_actions)
			{
				_currentActions.Clear();
				_currentActions.AddRange(_actions);
				_actions.Clear();
			}
			foreach (var a in _currentActions)
			{
				a();
			}
			lock (_delayed)
			{
				_currentDelayed.Clear();
				_currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));
				foreach (var item in _currentDelayed)
					_delayed.Remove(item);
			}
			foreach (var delayed in _currentDelayed)
			{
				delayed.action();
			}
		}
		
		/// <summary>
		/// 请在主线程内调用启动逻辑
		/// </summary>
		public static void StartUp()
		{
			if (initialized || null != _current) return; 
			Initialize();
		}
	}
}