package cz.xtf.testhelpers.image;

import com.google.gson.Gson;
import cz.xtf.core.image.Image;
import cz.xtf.core.openshift.OpenShift;
import cz.xtf.core.waiting.Waiters;
import io.fabric8.openshift.api.model.ImageStreamTag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
import org.jboss.dmr.Property;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
public class ImageMetadata {

	/**
	 * Creates ImageStream in provided OpenShift context and pulls back ImageStreamTag with imageUrl metadata.
	 *
	 * @param imageUrl  image url to initialize new instance of this object
	 * @param openShift context for creating ImageStream and retrieving image metadata
	 * @return new instance
	 */
	public static ImageMetadata prepare(OpenShift openShift, String imageUrl) {
		return ImageMetadata.prepare(openShift, Image.from(imageUrl));
	}

	public static ImageMetadata prepare(OpenShift openShift, Image image) {
		openShift.createImageStream(image.getImageStream());

		Waiters.sleep(TimeUnit.SECONDS, 10, "Giving OpenShift instance time to download image metadata.");
		ImageStreamTag isTag = openShift.imageStreamTags().withName(image.getRepo() + ":" + image.getMajorTag()).get();

		return new ImageMetadata(ModelNode.fromJSONString(new Gson().toJson(isTag.getImage().getDockerImageMetadata().getAdditionalProperties())));
	}

	private final ModelNode metadata;

	private ImageMetadata(ModelNode metadata) {
		this.metadata = metadata;
	}

	/**
	 * Returns labels on Config:Labels path.
	 *
	 * @return map of labels
	 */
	public Map<String, String> labels() {
		return metadata.get("Config", "Labels").asPropertyList().stream().collect(Collectors.toMap(Property::getName, property -> property.getValue().asString()));
	}

	/**
	 * Returns default container command on Config:Cmd path
	 *
	 * @return default command
	 */
	public String command() {
		return metadata.get("Config", "Cmd").get(0).asString();
	}

	/**
	 * Returns image environments of Config:Env path
	 *
	 * @return map of environments
	 */
	public Map<String, String> envs() {
		final Map<String, String> env = new HashMap<>();

		metadata.get("Config", "Env").asList().forEach(
				node -> {
					String[] keyValue = node.asString().split("=", 2);
					env.put(keyValue[0], keyValue[1]);
				}
		);

		return Collections.unmodifiableMap(env);
	}

	/**
	 * Returns integer set of exposed ports by specified protocol (eg. tcp, udp).
	 *
	 * @return port set
	 */
	public Set<Integer> exposedPorts(String protocol) {
		final Set<Integer> result = new HashSet<>();
		final ModelNode exposedPorts = metadata.get("Config", "ExposedPorts");

		if (exposedPorts.getType() != ModelType.UNDEFINED) {
			exposedPorts.keys().forEach(
					portDef -> {
						final String[] split = portDef.split("/");
						if (StringUtils.isBlank(protocol) || split[1].equalsIgnoreCase(protocol)) {
							result.add(Integer.parseInt(split[0]));
						}
					}
			);
		}

		return result;
	}
}

@@ -129,16 +129,57 @@
 nShift;%0A
+import cz.xtf.core.waiting.SimpleWaiter;%0A
 import c
@@ -203,17 +203,16 @@
 g.Waiter
-s
 ;%0Aimport
@@ -293,16 +293,17 @@
 .Slf4j;%0A
+%0A
 import o
@@ -582,27 +582,25 @@
 til.
-concurrent.TimeUnit
+function.Supplier
 ;%0Aim
@@ -1256,107 +1256,205 @@
 %0A%0A%09%09
-Waiters.sleep(TimeUnit.SECONDS, 10, %22Giving OpenShift instance time to download image metadata.%22);%0A
+Supplier%3CImageStreamTag%3E imageStreamTagSupplier = () -%3E openShift.imageStreamTags().withName(image.getRepo() + %22:%22 + image.getMajorTag()).get();%0A%09%09Waiter metadataWaiter = new SimpleWaiter(() -%3E %7B%0A%09
 %09%09Im
@@ -1474,26 +1474,16 @@
 isTag = 
-openShift.
 imageStr
@@ -1492,69 +1492,340 @@
 mTag
-s().withName(i
+Supplier.get();%0A%09%09%09if (isTag != null && isTag.getImage() != null && isTag.getI
 mage
+()
 .get
-Repo() + %22:%22 + i
+DockerImageMetadata() != null && isTag.getI
 mage
+()
 .get
-MajorTag()).get
+DockerImageMetadata().getAdditionalProperties() != null) %7B%0A%09%09%09%09return true;%0A%09%09%09%7D%0A%09%09%09return false;%0A%09%09%7D, %22Giving OpenShift instance time to download image metadata.%22);%0A%0A%09%09metadataWaiter.waitFor
 ();%0A
@@ -1896,20 +1896,43 @@
 toJson(i
-sTag
+mageStreamTagSupplier.get()
 .getImag

use waiter instead of the hardcoded 10s wait