package speiger.src.coreengine.assets.base;

import java.io.Closeable;
import java.io.IOException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.Consumer;
import java.util.function.Supplier;

import speiger.src.collections.ints.functions.consumer.IntObjectConsumer;
import speiger.src.collections.objects.collections.ObjectIterable;
import speiger.src.collections.objects.collections.ObjectIterator;
import speiger.src.collections.objects.functions.consumer.ObjectObjectConsumer;
import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.lists.ObjectList;

public class MultiAsset implements Closeable, ObjectIterable<IAsset> {
	ObjectList<IAsset> assets;
	
	public MultiAsset(IAsset...assets) {
		this(ObjectArrayList.wrap(assets));
	}
	
	public MultiAsset(ObjectList<IAsset> assets) {
		this.assets = assets.unmodifiable();
	}
	
	@Override
	public void close() {
		if(assets != null) {
			assets.forEach(IAsset::close);
			assets = null;
		}
	}
	
	public int size() {
		return assets.size();
	}
	
	public IAsset get(int index) {
		return assets.get(index);
	}
	
	public <T> Iterable<T> map(AssetMapper<T> mappingFunction, Supplier<T> defaultValue) {
		return () -> new Iterator<T>() {
			int index = 0;
			int size = assets.size();
			@Override
			public boolean hasNext() { return index < size; }
			@Override
			public T next() {
				if(!hasNext()) throw new NoSuchElementException();
				try { return mappingFunction.apply(assets.get(index++)); }
				catch(IOException e) {
					e.printStackTrace();
					return defaultValue.get();
				} 
			}
		};
	}
	
	@Override
	public void forEach(Consumer<? super IAsset> action) {
		assets.forEach(action);
	}
	
	@Override
	public <E> void forEach(E input, ObjectObjectConsumer<E, IAsset> action) {
		assets.forEach(input, action);
	}
	
	@Override
	public void forEachIndexed(IntObjectConsumer<IAsset> action) {
		assets.forEachIndexed(action);
	}

	@Override
	public ObjectIterator<IAsset> iterator() {
		return assets.iterator();
	}
	
	public static interface AssetMapper<T> {
		public T apply(IAsset asset) throws IOException;
	}
}
