// Path: src/main/java/fabzo/kraken/handler/docker/callbacks/LogContainerResultCallback.java
// @Slf4j
// public class LogContainerResultCallback extends ResultCallbackTemplate<LogContainerResultCallback, Frame> {
//     private final String logPrefix;
// 
//     public LogContainerResultCallback(final String logPrefix) {
//         this.logPrefix = logPrefix;
//     }
// 
//     @Override
//     public void onNext(final Frame item) {
//         log.info("[{}] {}", logPrefix, item.toString());
//     }
// }
// 
// Path: src/main/java/fabzo/kraken/handler/docker/callbacks/NoLogPullImageResultCallback.java
// public class NoLogPullImageResultCallback extends NoLogResultCallbackTemplate<NoLogPullImageResultCallback, PullResponseItem> {
// 
//     private static final Logger LOGGER = LoggerFactory.getLogger(NoLogPullImageResultCallback.class);
// 
//     @CheckForNull
//     private PullResponseItem latestItem = null;
// 
//     @Override
//     public void onNext(PullResponseItem item) {
//         this.latestItem = item;
//         LOGGER.debug(item.toString());
//     }
// 
//     /**
//      * Awaits the image to be pulled successful.
//      *
//      * @throws DockerClientException
//      *             if the pull fails.
//      */
//     public void awaitSuccess() {
//         try {
//             awaitCompletion();
//         } catch (InterruptedException e) {
//             throw new DockerClientException("", e);
//         }
// 
//         if (latestItem == null) {
//             throw new DockerClientException("Could not pull image");
//         } else if (!latestItem.isPullSuccessIndicated()) {
//             String message = (latestItem.getError() != null) ? latestItem.getError() : latestItem.getStatus();
//             throw new DockerClientException("Could not pull image: " + message);
//         }
//     }
// }
// 
// Path: src/main/java/fabzo/kraken/utils/ShutdownHookManager.java
// public class ShutdownHookManager {
//     private static final PriorityQueue<ShutdownHookEntry> shutdownHooks = new PriorityQueue<>((o1, o2) -> Integer.compare(o2.priority, o1.priority));
// 
//     static {
//         Runtime.getRuntime().addShutdownHook(new Thread(ShutdownHookManager::executeShutdownHooks));
//     }
// 
//     private static void executeShutdownHooks() {
//         synchronized (shutdownHooks) {
//             ShutdownHookEntry entry;
//             while ((entry = shutdownHooks.poll()) != null) {
//                 entry.hook.run();
//             }
//         }
//     }
// 
//     public static void addHook(final int priority, final Runnable shutdownHook) {
//         ObjectUtil.checkNotNull(shutdownHook, "Shutdown hook should not be null");
//         synchronized (shutdownHooks) {
//             shutdownHooks.add(new ShutdownHookEntry(priority, shutdownHook));
//         }
//     }
// 
//     public static class ShutdownHookEntry {
//         public int priority;
//         public Runnable hook;
// 
//         public ShutdownHookEntry(final int priority, final Runnable hook) {
//             this.priority = priority;
//             this.hook = hook;
//         }
//     }
// }


import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerCmd;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import fabzo.kraken.handler.docker.callbacks.LogContainerResultCallback;
import fabzo.kraken.handler.docker.callbacks.NoLogPullImageResultCallback;
import fabzo.kraken.utils.ShutdownHookManager;
import io.vavr.collection.List;
import io.vavr.control.Try;
import lombok.val;
package fabzo.kraken.handler.docker;


public class DockerCommands {
    private static final String API_VERSION = "1.23";
    private static final boolean VERIFY_TLS = false;

    private final String dockerSocket;
    private final DockerClient dockerClient;
    private List<DockerClient> logDockerClients = List.empty();

    public DockerCommands(final String dockerSocket, final String dockerRegistry) {
        this.dockerSocket = dockerSocket;
        this.dockerClient = newDockerClient(dockerSocket, dockerRegistry);

        ShutdownHookManager.addHook(1, this::cleanup);
    }

    private void cleanup() {
        Try.run(dockerClient::close);
        logDockerClients.forEach(client -> Try.run(client::close));
    }

    private DockerClient newDockerClient(final String dockerSocket, final String dockerRegistry) {
        val dockerConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost(dockerSocket)
                .withDockerTlsVerify(VERIFY_TLS)
                .withApiVersion(API_VERSION)
                .withRegistryUrl(dockerRegistry)
                .build();

        return DockerClientBuilder.getInstance(dockerConfig).build();
    }

    public void pullImage(final String image, final String tag) {
        dockerClient.pullImageCmd(image + ":" + tag)
// Path: src/main/java/fabzo/kraken/handler/docker/callbacks/LogContainerResultCallback.java
// @Slf4j
// public class LogContainerResultCallback extends ResultCallbackTemplate<LogContainerResultCallback, Frame> {
//     private final String logPrefix;
// 
//     public LogContainerResultCallback(final String logPrefix) {
//         this.logPrefix = logPrefix;
//     }
// 
//     @Override
//     public void onNext(final Frame item) {
//         log.info("[{}] {}", logPrefix, item.toString());
//     }
// }
// 
// Path: src/main/java/fabzo/kraken/handler/docker/callbacks/NoLogPullImageResultCallback.java
// public class NoLogPullImageResultCallback extends NoLogResultCallbackTemplate<NoLogPullImageResultCallback, PullResponseItem> {
// 
//     private static final Logger LOGGER = LoggerFactory.getLogger(NoLogPullImageResultCallback.class);
// 
//     @CheckForNull
//     private PullResponseItem latestItem = null;
// 
//     @Override
//     public void onNext(PullResponseItem item) {
//         this.latestItem = item;
//         LOGGER.debug(item.toString());
//     }
// 
//     /**
//      * Awaits the image to be pulled successful.
//      *
//      * @throws DockerClientException
//      *             if the pull fails.
//      */
//     public void awaitSuccess() {
//         try {
//             awaitCompletion();
//         } catch (InterruptedException e) {
//             throw new DockerClientException("", e);
//         }
// 
//         if (latestItem == null) {
//             throw new DockerClientException("Could not pull image");
//         } else if (!latestItem.isPullSuccessIndicated()) {
//             String message = (latestItem.getError() != null) ? latestItem.getError() : latestItem.getStatus();
//             throw new DockerClientException("Could not pull image: " + message);
//         }
//     }
// }
// 
// Path: src/main/java/fabzo/kraken/utils/ShutdownHookManager.java
// public class ShutdownHookManager {
//     private static final PriorityQueue<ShutdownHookEntry> shutdownHooks = new PriorityQueue<>((o1, o2) -> Integer.compare(o2.priority, o1.priority));
// 
//     static {
//         Runtime.getRuntime().addShutdownHook(new Thread(ShutdownHookManager::executeShutdownHooks));
//     }
// 
//     private static void executeShutdownHooks() {
//         synchronized (shutdownHooks) {
//             ShutdownHookEntry entry;
//             while ((entry = shutdownHooks.poll()) != null) {
//                 entry.hook.run();
//             }
//         }
//     }
// 
//     public static void addHook(final int priority, final Runnable shutdownHook) {
//         ObjectUtil.checkNotNull(shutdownHook, "Shutdown hook should not be null");
//         synchronized (shutdownHooks) {
//             shutdownHooks.add(new ShutdownHookEntry(priority, shutdownHook));
//         }
//     }
// 
//     public static class ShutdownHookEntry {
//         public int priority;
//         public Runnable hook;
// 
//         public ShutdownHookEntry(final int priority, final Runnable hook) {
//             this.priority = priority;
//             this.hook = hook;
//         }
//     }
// }


// Path: src/main/java/fabzo/kraken/handler/docker/DockerCommands.java
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerCmd;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import fabzo.kraken.handler.docker.callbacks.LogContainerResultCallback;
import fabzo.kraken.handler.docker.callbacks.NoLogPullImageResultCallback;
import fabzo.kraken.utils.ShutdownHookManager;
import io.vavr.collection.List;
import io.vavr.control.Try;
import lombok.val;

package fabzo.kraken.handler.docker;


public class DockerCommands {
    private static final String API_VERSION = "1.23";
    private static final boolean VERIFY_TLS = false;

    private final String dockerSocket;
    private final DockerClient dockerClient;
    private List<DockerClient> logDockerClients = List.empty();

    public DockerCommands(final String dockerSocket, final String dockerRegistry) {
        this.dockerSocket = dockerSocket;
        this.dockerClient = newDockerClient(dockerSocket, dockerRegistry);

        ShutdownHookManager.addHook(1, this::cleanup);
    }

    private void cleanup() {
        Try.run(dockerClient::close);
        logDockerClients.forEach(client -> Try.run(client::close));
    }

    private DockerClient newDockerClient(final String dockerSocket, final String dockerRegistry) {
        val dockerConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost(dockerSocket)
                .withDockerTlsVerify(VERIFY_TLS)
                .withApiVersion(API_VERSION)
                .withRegistryUrl(dockerRegistry)
                .build();

        return DockerClientBuilder.getInstance(dockerConfig).build();
    }

    public void pullImage(final String image, final String tag) {
        dockerClient.pullImageCmd(image + ":" + tag)
                .exec(new NoLogPullImageResultCallback())