using System;
using System.Collections;
using System.Collections.Generic;
using Swan.Configuration;
namespace Swan.Collections {
///
/// Implements a collection of components.
/// Each component in the collection may be given a unique name for later retrieval.
///
/// The type of components in the collection.
///
public class ComponentCollection : ConfiguredObject, IComponentCollection {
private readonly List _components = new List();
private readonly List<(String, T)> _componentsWithSafeNames = new List<(String, T)>();
private readonly Dictionary _namedComponents = new Dictionary();
///
public Int32 Count => this._components.Count;
///
public IReadOnlyDictionary Named => this._namedComponents;
///
public IReadOnlyList<(String SafeName, T Component)> WithSafeNames => this._componentsWithSafeNames;
///
public T this[Int32 index] => this._components[index];
///
public T this[String key] => this._namedComponents[key];
///
public IEnumerator GetEnumerator() => this._components.GetEnumerator();
///
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this._components).GetEnumerator();
///
/// The collection is locked.
public void Add(String name, T component) {
this.EnsureConfigurationNotLocked();
if(name != null) {
if(name.Length == 0) {
throw new ArgumentException("Component name is empty.", nameof(name));
}
if(this._namedComponents.ContainsKey(name)) {
throw new ArgumentException("Duplicate component name.", nameof(name));
}
}
if(component == null) {
throw new ArgumentNullException(nameof(component));
}
if(this._components.Contains(component)) {
throw new ArgumentException("Component has already been added.", nameof(component));
}
this._components.Add(component);
this._componentsWithSafeNames.Add((name ?? $"<{component.GetType().Name}>", component));
if(name != null) {
this._namedComponents.Add(name, component);
}
}
///
/// Locks the collection, preventing further additions.
///
public void Lock() => this.LockConfiguration();
}
}