using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using Decal.Interop.Filters;

namespace Decal.Adapter.Wrappers;

/// <summary>
/// Defines a collection of WorldObjects
/// </summary>
public class WorldObjectCollection : GenericDisposableWrapper<WorldIterator>, IEnumerable<WorldObject>, IEnumerable
{
	public class Iterator : IEnumerator<WorldObject>, IDisposable, IEnumerator
	{
		private WorldObjectCollection collection;

		private WorldObject current;

		public WorldObject Current
		{
			get
			{
				if (current == null)
				{
					MoveNext();
				}
				return current;
			}
		}

		object IEnumerator.Current
		{
			get
			{
				if (current == null)
				{
					MoveNext();
				}
				return current;
			}
		}

		internal Iterator(WorldObjectCollection collection)
		{
			this.collection = collection;
			Reset();
		}

		public void Dispose()
		{
			collection = null;
		}

		public bool MoveNext()
		{
			Decal.Interop.Filters.WorldObject ppObject = null;
			bool num = collection.Wrapped.Next(ref ppObject);
			if (num && ppObject != null)
			{
				current = collection.wf.GetCachedWorldObject(ppObject);
			}
			return num;
		}

		public void Reset()
		{
			collection.Wrapped.Reset();
		}
	}

	private WorldObject current;

	private WorldFilter wf;

	private IEnumerator<WorldObject> myEnum;

	/// <summary>
	/// Returns the number of items in the collection
	/// </summary>
	public int Count => base.Wrapped.Count;

	/// <summary>
	/// Returns the number of items represented by the collection, taking into account stacks of items.
	/// </summary>
	public int Quantity => base.Wrapped.Quantity;

	public WorldObject First
	{
		get
		{
			using IEnumerator<WorldObject> enumerator = GetEnumerator();
			return enumerator.Current;
		}
	}

	[Obsolete("Use Enumerators")]
	[EditorBrowsable(EditorBrowsableState.Never)]
	public WorldObject Current
	{
		get
		{
			if (myEnum == null)
			{
				myEnum = GetEnumerator();
			}
			return myEnum.Current;
		}
	}

	internal WorldObjectCollection(WorldFilter wf, WorldIterator obj)
		: base(obj)
	{
		this.wf = wf;
	}

	/// <summary>
	/// Apply a filter to this collection to limit what it returns
	/// </summary>
	/// <param name="filter">filter object</param>
	public void SetFilter(WorldObjectCollectionFilter filter)
	{
		filter?.ApplyFilter(base.Wrapped);
	}

	protected override void Dispose(bool userCalled)
	{
		if (myEnum != null)
		{
			myEnum.Dispose();
			myEnum = null;
		}
		base.Dispose(userCalled);
	}

	[Obsolete("Use Enumerators")]
	[EditorBrowsable(EditorBrowsableState.Never)]
	public bool MoveNext()
	{
		if (myEnum == null)
		{
			myEnum = GetEnumerator();
		}
		return myEnum.MoveNext();
	}

	[Obsolete("Use Enumerators")]
	[EditorBrowsable(EditorBrowsableState.Never)]
	public void Reset()
	{
		if (myEnum != null)
		{
			myEnum.Dispose();
			myEnum = null;
		}
	}

	public IEnumerator<WorldObject> GetEnumerator()
	{
		return new Iterator(this);
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return new Iterator(this);
	}
}
