package cz.xtf.core.openshift;

import cz.xtf.core.waiting.SimpleWaiter;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.client.dsl.ExecListener;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Response;

import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

@Slf4j
public class PodShell {
	private final OpenShift openShift;
	private final String podName;

	private final ByteArrayOutputStream baosOutput;
	private final ByteArrayOutputStream baosError;

	public PodShell(OpenShift openShift, String dcName) {
		this(openShift, openShift.getAnyPod(dcName));
	}

	public PodShell(OpenShift openShift, Pod pod) {
		this.openShift = openShift;
		this.podName = pod.getMetadata().getName();

		this.baosOutput = new ByteArrayOutputStream();
		this.baosError = new ByteArrayOutputStream();
	}

	public PodShellOutput executeWithBash(String command) {
		return execute("bash", "-c", command);
	}

	public PodShellOutput execute(String... commands) {
		baosOutput.reset();
		baosError.reset();

		StateExecListener execListener = new StateExecListener();
		SimpleWaiter simpleWaiter = new SimpleWaiter(execListener::hasExecutionFinished).timeout(TimeUnit.MINUTES, 1).reason("Waiting for " + Arrays.toString(commands) + " execution in '" + podName + "' pod.");

		openShift.pods().withName(podName).writingOutput(baosOutput).writingError(baosError).usingListener(execListener).exec(commands);

		simpleWaiter.waitFor();

		return new PodShellOutput(baosOutput.toString().trim(), baosError.toString().trim());
	}

	public class StateExecListener implements ExecListener {
		private final AtomicBoolean executionDone = new AtomicBoolean(false);

		@Override
		public void onOpen(Response response) {
			// DO NOTHING
		}

		@Override
		public void onFailure(Throwable throwable, Response response) {
			// DO NOTHING
		}

		@Override
		public void onClose(int i, String s) {
			executionDone.set(true);
		}

		public boolean hasExecutionFinished() {
			return executionDone.get();
		}
	}
}

@@ -62,24 +62,68 @@
 mpleWaiter;%0A
+import cz.xtf.core.waiting.WaiterException;%0A
 import io.fa
@@ -1214,38 +1214,143 @@
 ();%0A
+%0A
 %09%09
-SimpleWaiter simpleWaiter = 
+openShift.pods().withName(podName).writingOutput(baosOutput).writingError(baosError).usingListener(execListener).exec(commands);%0A%0A%09%09
 new 
@@ -1522,168 +1522,275 @@
 d.%22)
-;%0A%0A%09%09openShift.pods().withName(podName).writingOutput(baosOutput).writingError(baosError).usingListener(execListener).exec(commands);%0A%0A%09%09simpleWaiter.waitFor();
+.waitFor();%0A%09%09try %7B%0A%09%09%09new SimpleWaiter(() -%3E baosOutput.size() %3E 0 %7C%7C baosError.size() %3E 0).timeout(TimeUnit.SECONDS, 10).waitFor();%0A%09%09%7D catch (WaiterException e) %7B%0A%09%09%09log.warn(%22Output from PodShell's execution didn't appear in 10 seconds after channel close.%22);%0A%09%09%7D
 %0A%0A%09%09

Add waiter for stabilizating output