package io.fabric8.maven.docker.util;

import io.fabric8.maven.docker.access.AuthConfig;
import io.fabric8.maven.docker.access.util.ExternalCommand;
import org.apache.maven.plugin.MojoExecutionException;
import org.json.JSONObject;
import org.json.JSONTokener;

import java.io.IOException;

public class CredentialHelperClient {

    static final String SECRET_KEY = "Secret";
    static final String USERNAME_KEY = "Username";
    private final String credentialHelperName;
    private final Logger log;

    public CredentialHelperClient(Logger log, String credentialsStore) {
        this.log = log;
        credentialHelperName = "docker-credential-" + credentialsStore;
    }

    public String getName() {
        return credentialHelperName;
    }

    public String getVersion() throws MojoExecutionException {
        try {
            return new VersionCommand().getVersion();
        } catch (IOException e) {
            throw new MojoExecutionException("Error getting the version of the configured credential helper",e);
        }
    }

    public AuthConfig getAuthConfig(String registryToLookup) throws MojoExecutionException {
        try {
            final GetCommand getCommand = new GetCommand();
            return toAuthConfig(getCommand.getCredentialNode("https://" + registryToLookup));
        } catch (IOException e) {
            throw new MojoExecutionException("Error getting the credentials for " + registryToLookup + " from the configured credential helper",e);
        }
    }

    private AuthConfig toAuthConfig(JSONObject credential){
        if (credential == null) {
            return null;
        }
        String password = credential.getString(CredentialHelperClient.SECRET_KEY);
        String userKey = credential.getString(CredentialHelperClient.USERNAME_KEY);
        return new AuthConfig(userKey,password, null,null);
    }

    // docker-credential-XXX version
    private class VersionCommand extends ExternalCommand {

        private String version;

        VersionCommand() {
            super(CredentialHelperClient.this.log);
        }

        @Override
        protected String[] getArgs() {
            return new String[]{CredentialHelperClient.this.credentialHelperName,"version"};
        }

        @Override
        protected void processLine(String line) {
            log.info("Credentials helper reply for \"%s\" is %s",CredentialHelperClient.this.credentialHelperName,line);
            version = line;
        }

        public String getVersion() throws IOException {
            execute();
            if (version == null) {
                log.verbose("The credentials helper \"%s\" didn't return a version string",CredentialHelperClient.this.credentialHelperName);
            }
            return version;
        }
    }

    // echo <registryToLookup> | docker-credential-XXX get
    private class GetCommand extends ExternalCommand {

        private String reply;

        GetCommand() {
            super(CredentialHelperClient.this.log);
        }

        @Override
        protected String[] getArgs() {
            return new String[]{CredentialHelperClient.this.credentialHelperName,"get"};
        }

        @Override
        protected void processLine(String line) {
            reply = line;
        }

        public JSONObject getCredentialNode(String registryToLookup) throws IOException {
            try {
                execute(registryToLookup);
            } catch (IOException ex) {
                if (getStatusCode() == 1) {
                    return null;
                } else {
                    throw ex;
                }
            }
            JSONObject credentials = new JSONObject(new JSONTokener(reply));
            if (!credentials.has(SECRET_KEY) || !credentials.has(USERNAME_KEY)) {
                return null;
            }
            return credentials;
        }
    }
}

@@ -32,16 +32,94 @@
 .util;%0A%0A
+import com.google.common.base.Joiner;%0Aimport com.google.common.collect.Lists;%0A
 import i
@@ -360,16 +360,39 @@
 ception;
+%0Aimport java.util.List;
 %0A%0Apublic
@@ -3027,20 +3027,50 @@
 ate 
+List%3C
 String
+%3E
  reply
+ = Lists.newLinkedList()
 ;%0A%0A 
@@ -3396,23 +3396,26 @@
    reply
- = 
+.add(
 line
+)
 ;%0A      
@@ -3845,15 +3845,37 @@
 ner(
+Joiner.on('%5Cn').join(
 reply))
+)
 ;%0A  

Fix #930: Handle multi line credential helper responses