package de.siphalor.was.content;

import de.siphalor.was.content.pack.ContentPack;
import de.siphalor.was.content.resource.Resource;
import org.jetbrains.annotations.NotNull;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * The main manager that for holding and accessing resources in {@link ContentPack}s.
 */
public class ContentManager {
	/**
	 * All contained content packs
	 */
	private final List<ContentPack> packs = new LinkedList<>();

	/**
	 * Constructs a new, empty content manager.
	 */
	public ContentManager() {
	}

	/**
	 * Forgets all known content packs.
	 */
	public void clear() {
		packs.clear();
	}

	/**
	 * Adds a new content pack to this manager.
	 * @param pack The pack to add
	 */
	public void addPack(ContentPack pack) {
		packs.add(pack);
	}

	/**
	 * Gets all contained content packs.
	 * @return A collection of all packs
	 */
	public Collection<ContentPack> getPacks() {
		return packs;
	}

	/**
	 * Gets all resources that exist in all content packs in the given location with the given extension. Finds nested resources.
	 * @param location The base location where to find resources in
	 * @param type The file extension to look for (without the dot)
	 * @return A stream of all matching resources
	 */
	@NotNull
	public Stream<Resource> getResources(@NotNull String location, @NotNull String type) {
		return packs.stream().flatMap(pack -> pack.getResources(location, type)).distinct();
	}

	/**
	 * Gets the first resource with the given identifier.
	 * @param identifier The resource identifier
	 * @return The found resource or empty if none of the packs contains such a resource
	 * @see ContentManager#getAllOfResource(String)
	 */
	@NotNull
	public Optional<Resource> getResource(@NotNull String identifier) {
		Resource resource;
		for (ContentPack pack : packs) {
			resource = pack.getResource(identifier);
			if (resource != null) {
				return Optional.of(resource);
			}
		}
		return Optional.empty();
	}

	/**
	 * Gets all resources with the given identifier in the content packs.
	 * @param identifier The resource identifier to look for
	 * @return A stream of all those resources
	 * @see ContentManager#getResource(String)
	 */
	@NotNull
	public Stream<Resource> getAllOfResource(@NotNull String identifier) {
		return packs.stream().flatMap(pack -> Stream.ofNullable(pack.getResource(identifier)));
	}
}
