package org.jboss.windup.bootstrap.commands.addons;

import java.util.concurrent.atomic.AtomicBoolean;

import org.jboss.forge.furnace.Furnace;
import org.jboss.forge.furnace.addons.AddonId;
import org.jboss.forge.furnace.impl.addons.AddonRepositoryImpl;
import org.jboss.forge.furnace.manager.impl.AddonManagerImpl;
import org.jboss.forge.furnace.manager.maven.addon.MavenAddonDependencyResolver;
import org.jboss.forge.furnace.manager.request.AddonActionRequest;
import org.jboss.forge.furnace.manager.spi.AddonDependencyResolver;
import org.jboss.forge.furnace.versions.SingleVersion;
import org.jboss.forge.furnace.versions.Version;
import org.jboss.forge.furnace.versions.Versions;
import org.jboss.windup.bootstrap.commands.Command;
import org.jboss.windup.bootstrap.commands.CommandPhase;
import org.jboss.windup.bootstrap.commands.CommandResult;
import org.jboss.windup.bootstrap.commands.FurnaceDependent;

/**
 * @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
 */
public class InstallAddonCommand extends AbstractAddonCommand implements Command, FurnaceDependent {
    private Furnace furnace;
    private String addonId;
    private AtomicBoolean batchMode;

    public InstallAddonCommand(String addonId, AtomicBoolean batchMode) {
        this.addonId = addonId;
        this.batchMode = batchMode;
    }

    @Override
    public void setFurnace(Furnace furnace) {
        this.furnace = furnace;
    }

    @Override
    public CommandResult execute() {
        install(addonId, batchMode.get());
        return CommandResult.EXIT;
    }

    void install(String coordinates, boolean batchMode) {
        Version runtimeAPIVersion = AddonRepositoryImpl.getRuntimeAPIVersion();
        try {
            AddonDependencyResolver resolver = new MavenAddonDependencyResolver();
            AddonManagerImpl addonManager = new AddonManagerImpl(furnace, resolver);

            AddonId addonId;

            coordinates = convertColonVersionToComma(coordinates);

            // This allows windup --install maven
            if (coordinates.matches(artifactWithCommaVersionPattern)) {
                addonId = AddonId.fromCoordinates(coordinates);
            } else if (coordinates.matches(artifactPattern)) {
                AddonId[] versions = resolver.resolveVersions(coordinates).get();
                String coordinate = coordinates;

                if (versions.length == 0) {
                    throw new IllegalArgumentException("No Artifact version found for " + coordinate);
                } else {
                    AddonId selected = null;
                    for (int i = versions.length - 1; selected == null && i >= 0; i--) {
                        String apiVersion = resolver.resolveAPIVersion(versions[i]).get();
                        if (apiVersion != null
                                && Versions.isApiCompatible(runtimeAPIVersion, SingleVersion.valueOf(apiVersion))) {
                            selected = versions[i];
                        }
                    }
                    if (selected == null) {
                        throw new IllegalArgumentException("No compatible addon API version found for " + coordinate
                                + " for API " + runtimeAPIVersion);
                    }

                    addonId = selected;
                }
            } else {
                throw new IllegalArgumentException("Unrecognized format: " + coordinates + ", format must match: GROUP_ID:ARTIFACT_ID:VERSION");
            }

            AddonActionRequest request = addonManager.install(addonId);
            System.out.println(request);
            if (!batchMode) {
                String result = System.console().readLine("Confirm installation [Y/n]? ");
                if ("n".equalsIgnoreCase(result.trim())) {
                    System.out.println("Installation aborted.");
                    return;
                }
            }
            request.perform();
            System.out.println("Installation completed successfully.");
            System.out.println();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("> Forge version [" + runtimeAPIVersion + "]");
        }
    }

    @Override
    public CommandPhase getPhase() {
        return CommandPhase.POST_CONFIGURATION;
    }
}
