package org.kohsuke.github;

import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;

/**
 * @since 1.59
 */
public class GitHubBuilder {
    private String endpoint = GitHub.GITHUB_URL;
    
    // default scoped so unit tests can read them.
    /* private */ String user;
    /* private */ String password;
    /* private */ String oauthToken;
    
    private HttpConnector connector;

    public GitHubBuilder() {
    }

    /**
     * First check if the credentials are configured using the ~/.github properties file.
     * 
     * If no user is specified it means there is no configuration present so check the environment instead.
     * 
     * the system properties for the login, password or oauth environment variables.
     * 
     * @return the configured Builder from credentials defined on the system or in the environment.
     * 
     * @throws IOException
     */
    public static GitHubBuilder fromCredentials() throws IOException {
    	
    	GitHubBuilder builder;
		try {
			builder = fromPropertyFile();
			
			if (builder.user != null)
	    		return builder;
	    	else
	    		return fromEnvironment();
	    	
		} catch (FileNotFoundException e) {
			return fromEnvironment();
		}
    
    }
    
    public static GitHubBuilder fromEnvironment(String loginVariableName, String passwordVariableName, String oauthVariableName) throws IOException {
    	
    	
    	Properties env = new Properties();
    	
    	Object loginValue = System.getenv(loginVariableName);
    	
    	if (loginValue != null)
    		env.put("login", loginValue);
    	
    	Object passwordValue = System.getenv(passwordVariableName);
    	
    	if (passwordValue != null)
    		env.put("password", passwordValue);

    	Object oauthValue = System.getenv(oauthVariableName);
    	
    	if (oauthValue != null)
    		env.put("oauth", oauthValue);
    	
    	return fromProperties(env);

    }
    
    public static GitHubBuilder fromEnvironment() throws IOException {
    	
    	Properties props = new Properties();
    	
    	Map<String, String> env = System.getenv();
    	
    	for (Map.Entry<String, String> element : env.entrySet()) {
			
    		props.put(element.getKey(), element.getValue());
		}
    	
        return fromProperties(props);
    }
    
    public static GitHubBuilder fromPropertyFile() throws IOException {
        File homeDir = new File(System.getProperty("user.home"));
        File propertyFile = new File(homeDir, ".github");
        return fromPropertyFile(propertyFile.getPath());
    }
    
    public static GitHubBuilder fromPropertyFile(String propertyFileName) throws IOException {
        Properties props = new Properties();
        FileInputStream in = null;
        try {
            in = new FileInputStream(propertyFileName);
            props.load(in);
        } finally {
            IOUtils.closeQuietly(in);
        }
     
        return fromProperties(props);
    }
    
    public static GitHubBuilder fromProperties(Properties props) {
        GitHubBuilder self = new GitHubBuilder();
        self.withOAuthToken(props.getProperty("oauth"), props.getProperty("login"));
        self.withPassword(props.getProperty("login"), props.getProperty("password"));
        return self;
    }

    public GitHubBuilder withEndpoint(String endpoint) {
        this.endpoint = endpoint;
        return this;
    }
    public GitHubBuilder withPassword(String user, String password) {
        this.user = user;
        this.password = password;
        return this;
    }
    public GitHubBuilder withOAuthToken(String oauthToken) {
        return withOAuthToken(oauthToken, null);
    }
    public GitHubBuilder withOAuthToken(String oauthToken, String user) {
        this.oauthToken = oauthToken;
        this.user = user;
        return this;
    }
    public GitHubBuilder withConnector(HttpConnector connector) {
        this.connector = connector;
        return this;
    }

    public GitHub build() throws IOException {
        return new GitHub(endpoint, user, oauthToken, password, connector);
    }
}

@@ -804,84 +804,100 @@
   * 
-the system properties for the login, password or oauth environment variables
+If there is still no user it means there are no credentials defined and throw an IOException
 .%0A  
@@ -1036,16 +1036,113 @@
 xception
+ If there are no credentials defined in the ~/.github properties file or the process environment.
 %0A     */
@@ -1354,24 +1354,26 @@
    %09else
+ %7B
 %0A%09    %09%09
 return f
@@ -1368,94 +1368,534 @@
   %09%09
-return fromEnvironment();%0A%09    %09%0A%09%09%7D catch (FileNotFoundException e) %7B%0A%09%09%09return fromE
+%0A%09    %09%09// this is the case where the ~/.github file exists but has no content.%0A%09    %09%09%0A%09    %09%09builder = fromEnvironment();%0A%09    %09%09%0A%09    %09%09if (builder.user != null)%0A%09    %09%09%09return builder;%0A%09    %09%09else%0A%09    %09%09%09throw new IOException(%22Failed to resolve credentials from ~/.github or the environment.%22);%0A%09    %09%7D%0A%09    %09%0A%09%09%7D catch (FileNotFoundException e) %7B%0A%09%09%09builder = fromEnvironment();%0A%09%09%09%0A%09%09%09if (builder.user != null)%0A%09%09%09%09return builder;%0A%09%09%09else%0A%09%09%09%09throw new IOException(%22Failed to resolve credentials from ~/.github or the e
 nvir
@@ -1896,25 +1896,29 @@
  environment
-(
+.%22, e
 );%0A%09%09%7D%0A    %0A

Make Github.connect() fail if no credentials are setup