package com.simperium.client;

import com.simperium.SimperiumException;

import java.util.Objects;

public class AuthException extends SimperiumException {

    static public final String GENERIC_FAILURE_MESSAGE = "Invalid username or password";
    static public final String EXISTING_USER_FAILURE_MESSAGE = "Account already exists";
    static public final String UNVERIFIED_ACCOUNT_MESSAGE = "Account verification required";
    static public final String COMPROMISED_PASSWORD_MESSAGE = "Password has been compromised";
    static public final String COMPROMISED_PASSWORD_BODY = "compromised password";

    static public final int ERROR_STATUS_CODE = -1;

    public final FailureType failureType;

    public enum FailureType {
        INVALID_ACCOUNT, EXISTING_ACCOUNT, COMPROMISED_PASSWORD, UNVERIFIED_ACCOUNT
    }

    public AuthException(FailureType code, String message){
        super(message);
        failureType = code;
    }

    public AuthException(FailureType code, String message, Throwable cause){
        super(message, cause);
        failureType = code;
    }

    public static AuthException defaultException() {
        return exceptionForStatusCode(ERROR_STATUS_CODE);
    }

    public static AuthException exceptionForStatusCode(int statusCode) {
        return exceptionForStatusCode(statusCode, null);
    }

    public static AuthException exceptionForStatusCode(int statusCode, Throwable cause){
        switch (statusCode) {
            case 409:
                return new AuthException(FailureType.EXISTING_ACCOUNT, EXISTING_USER_FAILURE_MESSAGE, cause);
            case 403:
                return new AuthException(FailureType.UNVERIFIED_ACCOUNT, UNVERIFIED_ACCOUNT_MESSAGE, cause);
            case 401:
                // Code 401 can be obtain because credentials are wrong or the user's password has been compromised
                // To differentiate both responses, we check the response's body
                String message = cause != null && cause.getMessage() != null ? cause.getMessage().toLowerCase() : "";
                if (Objects.equals(message, COMPROMISED_PASSWORD_BODY)) {
                    return new AuthException(FailureType.COMPROMISED_PASSWORD, COMPROMISED_PASSWORD_MESSAGE, cause);
                }
            default:
                return new AuthException(FailureType.INVALID_ACCOUNT, GENERIC_FAILURE_MESSAGE, cause);
        }
    }
}
@@ -598,16 +598,101 @@
 ssword%22;
+%0A    static public final String VERIFICATION_REQUIRED_BODY = %22verification required%22;
 %0A%0A    st
@@ -1520,56 +1520,143 @@
     
-switch (statusCode) %7B%0A            case 409:%0A    
+String message = cause != null && cause.getMessage() != null ? cause.getMessage().toLowerCase() : %22%22;%0A        if (statusCode == 409) %7B%0A
     
@@ -1769,26 +1769,95 @@
     
-    case 403:%0A    
+%7D else if (statusCode == 403 && Objects.equals(message, VERIFICATION_REQUIRED_BODY)) %7B%0A
     
@@ -1969,357 +1969,40 @@
     
-    case 401:%0A                // Code 401 can be obtain because credentials are wrong or the user's password has been compromised%0A                // To differentiate both responses, we check the response's body%0A                String message = cause != null && cause.getMessage() != null ? cause.getMessage().toLowerCase() : %22%22;%0A                if (
+%7D else if (statusCode == 401 && 
 Obje
@@ -2059,32 +2059,24 @@
             
-      
-  
 return new A
@@ -2172,43 +2172,17 @@
     
-        %7D%0A            default:%0A    
+%7D else %7B%0A
     

Add check body for unverified accounts in 403 responses