// Path: src/com/salesforce/chatter/authentication/AuthenticationException.java
// public class AuthenticationException extends Exception {
// 
//     private static final long serialVersionUID = -4301971480963574988L;
// 
//     public AuthenticationException(Exception e) {
//         super(e);
//     }
// 
//     public AuthenticationException(String e) {
//         super(e);
//     }
// 
// }
// 
// Path: src/com/salesforce/chatter/authentication/ChatterAuthToken.java
// @JsonIgnoreProperties(ignoreUnknown = true)
// public class ChatterAuthToken {
// 
//     private String accessToken;
//     private String id;
//     private String issuedAt;
//     private String scope;
//     private String refreshToken;
//     private String instanceUrl;
//     private String signature;
// 
//     public ChatterAuthToken(String accessToken) {
//         this.accessToken = accessToken;
//     }
// 
//     /**
//      * <p>This constructor is mostly used by bean-like structures (currently the
//      * JSON parser uses this).</p>
//      */
//     public ChatterAuthToken() {
// 
//     }
// 
//     public String getAccessToken() {
//         return accessToken;
//     }
// 
//     public String getId() {
//         return id;
//     }
// 
//     public String getIssuedAt() {
//         return issuedAt;
//     }
// 
//     public String getScope() {
//         return scope;
//     }
// 
//     public String getRefreshToken() {
//         return refreshToken;
//     }
// 
//     public String getInstanceUrl() {
//         return instanceUrl;
//     }
// 
//     public String getSignature() {
//         return signature;
//     }
// }
// 
// Path: src/com/salesforce/chatter/authentication/IChatterData.java
// public interface IChatterData {
// 
//     /**
//      * @return String Something like "24.0"
//      */
//     public String getApiVersion();
// 
//     /**
//      * 
//      * @return String Something like "https://na10.salesforce.com"
//      */
//     public String getInstanceUrl();
// 
//     public ChatterAuthMethod getAuthMethod();
// 
//     public String getRefreshToken();
// 
//     public String getClientCode();
// 
//     public String getClientKey();
// 
//     public String getClientSecret();
// 
//     public String getUsername();
// 
//     public String getPassword();
// 
//     public String getClientCallback();
//     
// 	/**
// 	 * The Salesforce.com environment in which to perform authentication.
// 	 * Either PRODUCTION or TEST.
// 	 * 
// 	 * @return
// 	 */
//     public String getEnvironment();
// }
// 
// Path: src/com/salesforce/chatter/authentication/UnauthenticatedSessionException.java
// public class UnauthenticatedSessionException extends Exception {
// 
//     private static final long serialVersionUID = -827912609041441511L;
// 
//     public UnauthenticatedSessionException(String message) {
//         super(message);
//     }
// 
// }


import com.salesforce.chatter.authentication.ChatterAuthToken;
import com.salesforce.chatter.authentication.IChatterData;
import com.salesforce.chatter.authentication.UnauthenticatedSessionException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import com.salesforce.chatter.authentication.AuthenticationException;
/*******************************************************************************
 * Copyright (c) 2013, salesforce.com, inc.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided
 * that the following conditions are met:
 * 
 *    Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *    following disclaimer.
 * 
 *    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *    the following disclaimer in the documentation and/or other materials provided with the distribution.
 * 
 *    Neither the name of salesforce.com, inc. nor the names of its contributors may be used to endorse or
 *    promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/
package com.salesforce.chatter.authentication.methods;



/**
 * <p>Asks the user to get the verificationCode (clientSecret) and use {@link ClientSecretAuthentication} to complete the
 * authentication.</p>
 * 
 * @author jroel
 * @since 1.0
 * 
 */
public class InteractiveAuthentication extends AuthentificationMethod {

    private static final String TEST_VERIFICATION_URL = "https://test.salesforce.com/services/oauth2/authorize?response_type=code&client_id=__CLIENTID__&redirect_uri=__REDIRECTURI__";

	private int attempts = 3;

    private final IChatterData chatterData;

    public InteractiveAuthentication(IChatterData chatterData) {
        this.chatterData = chatterData;
    }

    /**
     * <p>Start the interactive authentication. It will ask the user to visit the authentication page and report back
     * the verification code.</p>
     * 
     * @return ChatterAuthToken When authenticated with success, the ChatterAuthToken will be returned
     * @throws IOException Thrown when a problem during I/O occurs
     * @throws AuthenticationException in case we got a String that looked like a Verification code, but was the wrong
     *         one
     * @throws UnauthenticatedSessionException Thrown if after several attempts no valid authentication token was
     *         created
     */
    public ChatterAuthToken authenticate() throws IOException, UnauthenticatedSessionException, AuthenticationException {
        boolean keepTrying = true;
        while (keepTrying) {
            // Request this from the user...
            System.out.println("Please visit the following URL and report back the verification code...");
            String uri = "TEST".equalsIgnoreCase(chatterData.getEnvironment()) ? TEST_VERIFICATION_URL : VERIFICATION_URL;
// Path: src/com/salesforce/chatter/authentication/AuthenticationException.java
// public class AuthenticationException extends Exception {
// 
//     private static final long serialVersionUID = -4301971480963574988L;
// 
//     public AuthenticationException(Exception e) {
//         super(e);
//     }
// 
//     public AuthenticationException(String e) {
//         super(e);
//     }
// 
// }
// 
// Path: src/com/salesforce/chatter/authentication/ChatterAuthToken.java
// @JsonIgnoreProperties(ignoreUnknown = true)
// public class ChatterAuthToken {
// 
//     private String accessToken;
//     private String id;
//     private String issuedAt;
//     private String scope;
//     private String refreshToken;
//     private String instanceUrl;
//     private String signature;
// 
//     public ChatterAuthToken(String accessToken) {
//         this.accessToken = accessToken;
//     }
// 
//     /**
//      * <p>This constructor is mostly used by bean-like structures (currently the
//      * JSON parser uses this).</p>
//      */
//     public ChatterAuthToken() {
// 
//     }
// 
//     public String getAccessToken() {
//         return accessToken;
//     }
// 
//     public String getId() {
//         return id;
//     }
// 
//     public String getIssuedAt() {
//         return issuedAt;
//     }
// 
//     public String getScope() {
//         return scope;
//     }
// 
//     public String getRefreshToken() {
//         return refreshToken;
//     }
// 
//     public String getInstanceUrl() {
//         return instanceUrl;
//     }
// 
//     public String getSignature() {
//         return signature;
//     }
// }
// 
// Path: src/com/salesforce/chatter/authentication/IChatterData.java
// public interface IChatterData {
// 
//     /**
//      * @return String Something like "24.0"
//      */
//     public String getApiVersion();
// 
//     /**
//      * 
//      * @return String Something like "https://na10.salesforce.com"
//      */
//     public String getInstanceUrl();
// 
//     public ChatterAuthMethod getAuthMethod();
// 
//     public String getRefreshToken();
// 
//     public String getClientCode();
// 
//     public String getClientKey();
// 
//     public String getClientSecret();
// 
//     public String getUsername();
// 
//     public String getPassword();
// 
//     public String getClientCallback();
//     
// 	/**
// 	 * The Salesforce.com environment in which to perform authentication.
// 	 * Either PRODUCTION or TEST.
// 	 * 
// 	 * @return
// 	 */
//     public String getEnvironment();
// }
// 
// Path: src/com/salesforce/chatter/authentication/UnauthenticatedSessionException.java
// public class UnauthenticatedSessionException extends Exception {
// 
//     private static final long serialVersionUID = -827912609041441511L;
// 
//     public UnauthenticatedSessionException(String message) {
//         super(message);
//     }
// 
// }


// Path: src/com/salesforce/chatter/authentication/methods/InteractiveAuthentication.java
import com.salesforce.chatter.authentication.ChatterAuthToken;
import com.salesforce.chatter.authentication.IChatterData;
import com.salesforce.chatter.authentication.UnauthenticatedSessionException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import com.salesforce.chatter.authentication.AuthenticationException;

/*******************************************************************************
 * Copyright (c) 2013, salesforce.com, inc.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided
 * that the following conditions are met:
 * 
 *    Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *    following disclaimer.
 * 
 *    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *    the following disclaimer in the documentation and/or other materials provided with the distribution.
 * 
 *    Neither the name of salesforce.com, inc. nor the names of its contributors may be used to endorse or
 *    promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/
package com.salesforce.chatter.authentication.methods;



/**
 * <p>Asks the user to get the verificationCode (clientSecret) and use {@link ClientSecretAuthentication} to complete the
 * authentication.</p>
 * 
 * @author jroel
 * @since 1.0
 * 
 */
public class InteractiveAuthentication extends AuthentificationMethod {

    private static final String TEST_VERIFICATION_URL = "https://test.salesforce.com/services/oauth2/authorize?response_type=code&client_id=__CLIENTID__&redirect_uri=__REDIRECTURI__";

	private int attempts = 3;

    private final IChatterData chatterData;

    public InteractiveAuthentication(IChatterData chatterData) {
        this.chatterData = chatterData;
    }

    /**
     * <p>Start the interactive authentication. It will ask the user to visit the authentication page and report back
     * the verification code.</p>
     * 
     * @return ChatterAuthToken When authenticated with success, the ChatterAuthToken will be returned
     * @throws IOException Thrown when a problem during I/O occurs
     * @throws AuthenticationException in case we got a String that looked like a Verification code, but was the wrong
     *         one
     * @throws UnauthenticatedSessionException Thrown if after several attempts no valid authentication token was
     *         created
     */
    public ChatterAuthToken authenticate() throws IOException, UnauthenticatedSessionException, AuthenticationException {
        boolean keepTrying = true;
        while (keepTrying) {
            // Request this from the user...
            System.out.println("Please visit the following URL and report back the verification code...");
            String uri = "TEST".equalsIgnoreCase(chatterData.getEnvironment()) ? TEST_VERIFICATION_URL : VERIFICATION_URL;
            uri = uri.replace("__CLIENTID__", chatterData.getClientKey());