// Path: arquillian-chameleon-container-model/src/main/java/org/arquillian/container/chameleon/spi/model/ContainerAdapter.java
// public class ContainerAdapter {
// 
//     private String version;
//     private Target.Type targetType;
//     private Adapter adapter;
//     private Dist dist;
//     private String[] gavExcludeExpression;
//     private String defaultProtocol;
// 
//     public ContainerAdapter(String version, Target.Type targetType, Adapter adapter, Dist dist,
//         String[] gavExcludeExpression, String defaultProtocol) {
//         this.version = version;
//         this.targetType = targetType;
//         this.adapter = adapter;
//         this.dist = dist;
//         this.gavExcludeExpression = gavExcludeExpression;
//         this.defaultProtocol = defaultProtocol;
//     }
// 
//     public Target.Type type() {
//         return targetType;
//     }
// 
//     public boolean overrideDefaultProtocol() {
//         return this.defaultProtocol != null;
//     }
// 
//     public String getDefaultProtocol() {
//         return defaultProtocol;
//     }
// 
//     public String adapterClass() {
//         return adapter.adapterClass();
//     }
// 
//     public String[] dependencies() {
//         return resolve(adapter.dependencies());
//     }
// 
//     public String distribution() {
//         return resolve(dist.coordinates());
//     }
// 
//     public String[] excludes() {
//         return resolve(gavExcludeExpression);
//     }
// 
//     public String[] configurationKeys() {
//         return adapter.configuration().keySet().toArray(new String[] {});
//     }
// 
//     public boolean requireDistribution() {
//         return adapter.requireDist();
//     }
// 
//     public Map<String, String> resolveConfiguration(Map<String, String> parameters) {
//         Map<String, String> configuration = adapter.configuration();
//         for (Map.Entry<String, String> entry : configuration.entrySet()) {
//             for (Map.Entry<String, String> parameter : parameters.entrySet()) {
//                 entry.setValue(resolve(parameter.getKey(), parameter.getValue(), entry.getValue()));
//             }
//         }
//         return configuration;
//     }
// 
//     private String[] resolve(String[] values) {
//         if (values == null) {
//             return new String[0];
//         }
//         String[] resolved = new String[values.length];
//         for (int i = 0; i < values.length; i++) {
//             resolved[i] = resolve(values[i]);
//         }
//         return resolved;
//     }
// 
//     private String resolve(String value) {
//         return resolve("version", version, value);
//     }
// 
//     private String resolve(String parameter, String value, String target) {
//         return target.replaceAll(Pattern.quote("${" + parameter + "}"), Matcher.quoteReplacement(value));
//     }
// }
// 
// Path: arquillian-chameleon-container-model/src/main/java/org/arquillian/container/chameleon/spi/model/Target.java
// public enum Type {
//     Remote, Managed, Embedded, Default;
// 
//     public static Type from(String name) {
//         for (Type type : Type.values()) {
//             if (type.name().equalsIgnoreCase(name)) {
//                 return type;
//             }
//         }
//         return null;
//     }
// 
// }
// 
// Path: arquillian-chameleon-extension/src/main/java/org/arquillian/container/chameleon/Utils.java
// public static MavenCoordinate toMavenCoordinate(String dep) {
//     return MavenCoordinates.createCoordinate(dep);
// }


import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import org.arquillian.container.chameleon.spi.model.ContainerAdapter;
import org.arquillian.container.chameleon.spi.model.Target.Type;
import org.arquillian.spacelift.Spacelift;
import org.arquillian.spacelift.execution.Execution;
import org.arquillian.spacelift.task.net.DownloadTool;
import org.jboss.arquillian.config.descriptor.api.ContainerDef;
import org.jboss.arquillian.core.api.threading.ExecutorService;
import org.jboss.shrinkwrap.api.GenericArchive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.exporter.ExplodedExporter;
import org.jboss.shrinkwrap.api.importer.ZipImporter;
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenCoordinate;
import static org.arquillian.container.chameleon.Utils.toMavenCoordinate;
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the @authors tag. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.arquillian.container.chameleon.controller;



public class DistributionController {

    private static final String PROGRESS_INDICATOR = ".";
    private static final int HALF_A_SECOND = 500;

    private ContainerAdapter targetAdapter;
    private String distributionDownloadFolder;

    public DistributionController(ContainerAdapter targetAdapter, String distributionDownloadFolder) {
        this.targetAdapter = targetAdapter;
        this.distributionDownloadFolder = distributionDownloadFolder;
    }

    public void setup(ContainerDef targetConfiguration, ExecutorService executor) throws Exception {
        if (requireDistribution(targetConfiguration)) {
            updateTargetConfiguration(targetConfiguration, resolveDistribution(executor));
        }
    }

    private boolean requireDistribution(ContainerDef targetConfiguration) {
        if (targetAdapter.requireDistribution() && requiredConfigurationNotSet(targetConfiguration, targetAdapter)) {
// Path: arquillian-chameleon-container-model/src/main/java/org/arquillian/container/chameleon/spi/model/ContainerAdapter.java
// public class ContainerAdapter {
// 
//     private String version;
//     private Target.Type targetType;
//     private Adapter adapter;
//     private Dist dist;
//     private String[] gavExcludeExpression;
//     private String defaultProtocol;
// 
//     public ContainerAdapter(String version, Target.Type targetType, Adapter adapter, Dist dist,
//         String[] gavExcludeExpression, String defaultProtocol) {
//         this.version = version;
//         this.targetType = targetType;
//         this.adapter = adapter;
//         this.dist = dist;
//         this.gavExcludeExpression = gavExcludeExpression;
//         this.defaultProtocol = defaultProtocol;
//     }
// 
//     public Target.Type type() {
//         return targetType;
//     }
// 
//     public boolean overrideDefaultProtocol() {
//         return this.defaultProtocol != null;
//     }
// 
//     public String getDefaultProtocol() {
//         return defaultProtocol;
//     }
// 
//     public String adapterClass() {
//         return adapter.adapterClass();
//     }
// 
//     public String[] dependencies() {
//         return resolve(adapter.dependencies());
//     }
// 
//     public String distribution() {
//         return resolve(dist.coordinates());
//     }
// 
//     public String[] excludes() {
//         return resolve(gavExcludeExpression);
//     }
// 
//     public String[] configurationKeys() {
//         return adapter.configuration().keySet().toArray(new String[] {});
//     }
// 
//     public boolean requireDistribution() {
//         return adapter.requireDist();
//     }
// 
//     public Map<String, String> resolveConfiguration(Map<String, String> parameters) {
//         Map<String, String> configuration = adapter.configuration();
//         for (Map.Entry<String, String> entry : configuration.entrySet()) {
//             for (Map.Entry<String, String> parameter : parameters.entrySet()) {
//                 entry.setValue(resolve(parameter.getKey(), parameter.getValue(), entry.getValue()));
//             }
//         }
//         return configuration;
//     }
// 
//     private String[] resolve(String[] values) {
//         if (values == null) {
//             return new String[0];
//         }
//         String[] resolved = new String[values.length];
//         for (int i = 0; i < values.length; i++) {
//             resolved[i] = resolve(values[i]);
//         }
//         return resolved;
//     }
// 
//     private String resolve(String value) {
//         return resolve("version", version, value);
//     }
// 
//     private String resolve(String parameter, String value, String target) {
//         return target.replaceAll(Pattern.quote("${" + parameter + "}"), Matcher.quoteReplacement(value));
//     }
// }
// 
// Path: arquillian-chameleon-container-model/src/main/java/org/arquillian/container/chameleon/spi/model/Target.java
// public enum Type {
//     Remote, Managed, Embedded, Default;
// 
//     public static Type from(String name) {
//         for (Type type : Type.values()) {
//             if (type.name().equalsIgnoreCase(name)) {
//                 return type;
//             }
//         }
//         return null;
//     }
// 
// }
// 
// Path: arquillian-chameleon-extension/src/main/java/org/arquillian/container/chameleon/Utils.java
// public static MavenCoordinate toMavenCoordinate(String dep) {
//     return MavenCoordinates.createCoordinate(dep);
// }


// Path: arquillian-chameleon-extension/src/main/java/org/arquillian/container/chameleon/controller/DistributionController.java
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import org.arquillian.container.chameleon.spi.model.ContainerAdapter;
import org.arquillian.container.chameleon.spi.model.Target.Type;
import org.arquillian.spacelift.Spacelift;
import org.arquillian.spacelift.execution.Execution;
import org.arquillian.spacelift.task.net.DownloadTool;
import org.jboss.arquillian.config.descriptor.api.ContainerDef;
import org.jboss.arquillian.core.api.threading.ExecutorService;
import org.jboss.shrinkwrap.api.GenericArchive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.exporter.ExplodedExporter;
import org.jboss.shrinkwrap.api.importer.ZipImporter;
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenCoordinate;
import static org.arquillian.container.chameleon.Utils.toMavenCoordinate;

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the @authors tag. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.arquillian.container.chameleon.controller;



public class DistributionController {

    private static final String PROGRESS_INDICATOR = ".";
    private static final int HALF_A_SECOND = 500;

    private ContainerAdapter targetAdapter;
    private String distributionDownloadFolder;

    public DistributionController(ContainerAdapter targetAdapter, String distributionDownloadFolder) {
        this.targetAdapter = targetAdapter;
        this.distributionDownloadFolder = distributionDownloadFolder;
    }

    public void setup(ContainerDef targetConfiguration, ExecutorService executor) throws Exception {
        if (requireDistribution(targetConfiguration)) {
            updateTargetConfiguration(targetConfiguration, resolveDistribution(executor));
        }
    }

    private boolean requireDistribution(ContainerDef targetConfiguration) {
        if (targetAdapter.requireDistribution() && requiredConfigurationNotSet(targetConfiguration, targetAdapter)) {
            if (targetAdapter.type() == Type.Embedded || targetAdapter.type() == Type.Managed) {