package de.siphalor.was.content.product;

import de.siphalor.was.content.ContentManager;
import de.siphalor.was.content.product.dynamic.DynamicProductType;
import de.siphalor.was.util.ResourceManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * A class which manages the loading and access to products.
 */
public class ProductManager implements ResourceManager<ProductType<?>> {
	/**
	 * Map with all {@link ProductType}s mapped by their ids.
	 */
	private final Map<String, ProductType<?>> productTypes = new HashMap<>();

	/**
	 * Removes all loaded products
	 */
	@Override
	public void clear() {
		productTypes.clear();
	}

	/**
	 * Loads all products from the given content manager.
	 * @param contentManager The content manager to load from
	 */
	public void reload(@NotNull ContentManager contentManager) {
		contentManager.getResources("products", "properties").forEach(resource -> {
			InputStream inputStream = resource.getInputStream();
			if (inputStream != null) {
				productTypes.put(resource.getId(), DynamicProductType.from(resource.getId(), inputStream));
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Gets a single product type by its id.
	 * @param id The id
	 * @return The associated product type or <code>null</code> if no product type with this id exists
	 */
	@Override
	@Nullable
	public ProductType<?> get(String id) {
		return productTypes.get(id);
	}

	@Override
	public void register(String id, ProductType<?> value) {
		productTypes.put(id, value);
	}

	/**
	 * Gets all loaded product types.
	 * @return All loaded product types
	 */
	@NotNull
	public Collection<ProductType<?>> getTypes() {
		return productTypes.values();
	}

	/**
	 * Returns a random product out of all product types. Randomness is distributed equally over all types not over the product variants.
	 * @param random The random instance to use
	 * @return A random product or <code>null</code> if no products are loaded
	 */
	@Nullable
	public Product randomProduct(Random random) {
		if (!productTypes.isEmpty()) {
			List<ProductType<?>> typeList = new ArrayList<>(productTypes.values());
			return typeList.get(random.nextInt(typeList.size())).randomProduct(random);
		}
		return null;
	}
}
