using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Cute;

public class AsyncJob
{
	private class Unit
	{
		public object action;

		public Action cancelAction;

		public Unit(object action, Action cancelAction)
		{
			this.action = action;
			this.cancelAction = cancelAction;
		}
	}

	private int num;

	private MonoBehaviour mono;

	private List<Unit> jobList = new List<Unit>();

	private bool isCancel;

	private int? _waitFramesBetweenJobs;

	private int _waitFramesBetweenJobsMin;

	private FramerateProfiler _framerateProfiler = new FramerateProfiler();

	public int WAIT_FRAMES_INCREMENT = 5;

	public int WAIT_FRAMES_DECREMENT = 1;

	public bool IsIdle
	{
		get
		{
			if (!isCancel)
			{
				return jobList.Count == 0;
			}
			return false;
		}
	}

	public int? WantedWaitFramesBetweenJobs
	{
		set
		{
			_waitFramesBetweenJobs = value;
			_waitFramesBetweenJobsMin = value.GetValueOrDefault();
		}
	}

	public AsyncJob(MonoBehaviour mono, int num)
	{
		this.mono = mono;
		this.num = num;
	}

	public void Add(IEnumerator enumerator)
	{
		jobList.Add(new Unit(enumerator, null));
	}

	public void Add(IEnumerator enumerator, Action calcelAction)
	{
		jobList.Add(new Unit(enumerator, calcelAction));
	}

	public void Add(Action action)
	{
		jobList.Add(new Unit(action, null));
	}

	public void Add(Action action, Action calcelAction)
	{
		jobList.Add(new Unit(action, calcelAction));
	}

	public void Cancel()
	{
		if (!isCancel && jobList.Count != 0)
		{
			isCancel = true;
			Add(CancelTerminator, CancelTerminator);
		}
	}

	public void CancelTerminator()
	{
		isCancel = false;
	}

	public void Start()
	{
		for (int i = 0; i < num; i++)
		{
			mono.StartCoroutine(MicroThread());
		}
		_framerateProfiler = new FramerateProfiler();
		mono.StartCoroutine(RunFpsProfiler());
	}

	private IEnumerator RunFpsProfiler()
	{
		_framerateProfiler.Init();
		while (true)
		{
			_framerateProfiler.Update();
			yield return null;
		}
	}

	private IEnumerator MicroThread()
	{
		while (true)
		{
			if (jobList.Count <= 0)
			{
				yield return null;
				continue;
			}
			Unit unit = jobList[0];
			jobList.RemoveAt(0);
			if (isCancel)
			{
				if (unit.cancelAction != null)
				{
					unit.cancelAction();
				}
			}
			else if (unit.action is IEnumerator)
			{
				yield return mono.StartCoroutine((IEnumerator)unit.action);
				if (!_waitFramesBetweenJobs.HasValue)
				{
					continue;
				}
				float? fps = _framerateProfiler.Fps;
				if (fps.HasValue)
				{
					if (fps < 20f)
					{
						_waitFramesBetweenJobs += WAIT_FRAMES_INCREMENT;
						_framerateProfiler.Init();
					}
					else if (fps > 30f)
					{
						_waitFramesBetweenJobs -= WAIT_FRAMES_INCREMENT;
						if (_waitFramesBetweenJobs.Value < _waitFramesBetweenJobsMin)
						{
							_waitFramesBetweenJobs = _waitFramesBetweenJobsMin;
						}
						_framerateProfiler.Init();
					}
				}
				yield return WaitFrames(_waitFramesBetweenJobs.Value);
			}
			else if (unit.action is Action)
			{
				((Action)unit.action)();
			}
		}
	}

	private static IEnumerator WaitFrames(int frameCount)
	{
		while (frameCount > 0)
		{
			frameCount--;
			yield return null;
		}
	}
}
