package de.siphalor.was;

import de.siphalor.was.content.ContentManager;
import de.siphalor.was.content.lang.I18n;
import de.siphalor.was.content.pack.ContentPack;
import de.siphalor.was.content.pack.JarContentPack;
import de.siphalor.was.content.product.Product;
import de.siphalor.was.content.product.ProductManager;
import de.siphalor.was.content.product.dynamic.DynamicProduct;
import de.siphalor.was.content.product.dynamic.DynamicProductType;
import de.siphalor.was.content.resource.Resource;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;

import javax.imageio.ImageIO;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Properties;
import java.util.stream.Stream;

public class ContentTests {
	static ContentManager contentManager;
	static ContentPack contentPack;

	@BeforeAll
	public static void prepareAll() {
		contentManager = new ContentManager();
		contentPack = new JarContentPack("", "content");
		contentManager.addPack(contentPack);
	}

	@Test
	public void areLangsUpToDate() throws IOException {
		Properties properties = new Properties();
		InputStream inputStream = contentManager.getResource("lang/en_us.properties").orElseThrow().getInputStream();
		properties.load(inputStream);

		Assertions.assertAll(contentManager.getResources("lang", "lang").flatMap(resource -> {
			if (resource.getId().equals("lang/en_us.properties")) {
				return Stream.empty();
			}
			Properties props = new Properties();
			return Stream.of(() -> {
				Assertions.assertDoesNotThrow(() -> props.load(resource.getInputStream()));
				Assertions.assertAll(properties.keySet().stream().map(key -> () -> {
							if (!key.toString().startsWith("langs.")) {
								Assertions.assertTrue(props.containsKey(key), "Missing lang key " + key + " for file " + resource.getId());
							}
						}
				));
			});
		}));
		contentManager.getResources("lang", "lang").forEach(resource -> {
		});
	}

	@Test
	public void productsI18n() {
		ProductManager productManager = new ProductManager();
		productManager.reload(contentManager);
		I18n i18n = I18n.getInstance();
		i18n.reload(contentManager);

		Assertions.assertAll(
				"Missing translations for products",
				productManager.getTypes().stream().flatMap(productType -> {
					String productKey = "products." + productType.getId();
					Stream<Executable> stream = Arrays.stream(productType.getProperties()).map(property -> () ->
							Assertions.assertTrue(
									i18n.containsKey(productKey + "." + property),
									() -> "Missing translation for property " + property + "@" + productType.getId() + ": " + productKey + "." + property
							)
					);
					stream = Stream.concat(stream, Stream.of(() -> Assertions.assertTrue(i18n.containsKey(productKey), "Missing translation for product name: " + productKey)));
					return stream;
				})
		);
	}

	@Test
	public void productImages() {
		ProductManager productManager = new ProductManager();
		productManager.reload(contentManager);

		Assertions.assertAll(productManager.getTypes().stream().flatMap(productType -> {
			if (productType instanceof DynamicProductType) {
				return ((DynamicProductType) productType).getVariations().values().stream().map(dynamicProduct -> () -> {
					Resource resource = contentManager.getResource(dynamicProduct.getTextureLocation()).orElse(null);
					Assertions.assertNotNull(resource,
							() -> "Couldn't find image resource for " + dynamicProduct.getTranslationKey()
									+ " with properties " + dynamicProduct.getPropertySpecifier()
									+ ": " + dynamicProduct.getTextureLocation()
					);
					Assertions.assertDoesNotThrow(() -> ImageIO.read(resource.getInputStream()),
							() -> "Failed to load image resource for " + dynamicProduct.getTranslationKey()
									+ "with properties " + dynamicProduct.getPropertySpecifier()
									+ ": " + dynamicProduct.getTextureLocation()
					);
				});
			}
			return Stream.empty();
		}));
	}
}
