package com.braintreepayments.api.models;

import android.os.Parcel;
import android.os.Parcelable;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * Class to parse and contain 3D Secure authentication responses
 */
public class ThreeDSecureAuthenticationResponse implements Parcelable {

    private static final String PAYMENT_METHOD_KEY = "paymentMethod";
    private static final String SUCCESS_KEY = "success";
    private static final String THREE_D_SECURE_INFO_KEY = "threeDSecureInfo";

    private CardNonce mCardNonce;
    private boolean mSuccess;
    private String mErrors;
    private String mException;
    private ThreeDSecureInfo mThreeDSecureInfo;

    /**
     * Used to parse a response from the Braintree Gateway to be used for 3D Secure.
     *
     * @param jsonString The json response from the Braintree Gateway 3D Secure authentication route.
     * @return The {@link ThreeDSecureAuthenticationResponse} to use when performing 3D Secure
     *         authentication.
     */
    public static ThreeDSecureAuthenticationResponse fromJson(String jsonString) {
        ThreeDSecureAuthenticationResponse authenticationResponse = new ThreeDSecureAuthenticationResponse();

        try {
            JSONObject json = new JSONObject(jsonString);

            JSONObject cardJson = json.optJSONObject(PAYMENT_METHOD_KEY);
            if (cardJson != null) {
                CardNonce cardNonce = new CardNonce();
                cardNonce.fromJson(cardJson);
                authenticationResponse.mCardNonce = cardNonce;
            }

            // TODO: We aren't currently getting a 'success' value for 3DS 2.0
            // The below check for "errors" can be removed once it is available
            if (json.has(SUCCESS_KEY)) {
                authenticationResponse.mSuccess = json.getBoolean(SUCCESS_KEY);
            }
            else if (!json.has("errors")) {
                authenticationResponse.mSuccess = true;
            }

            if (!authenticationResponse.mSuccess) {
                authenticationResponse.mErrors = jsonString;
            }

            authenticationResponse.mThreeDSecureInfo = ThreeDSecureInfo.fromJson(
                    json.optJSONObject(THREE_D_SECURE_INFO_KEY));
        } catch (JSONException e) {
            authenticationResponse.mSuccess = false;
        }

        return authenticationResponse;
    }

    /**
     * @deprecated ThreeDSecure WebView flow is deprecated. Use the browser-switch flow.
     * {@see https://developers.braintreepayments.com/guides/3d-secure/client-side/android/v2}
     */
    @Deprecated
    public static ThreeDSecureAuthenticationResponse fromException(String exception) {
        ThreeDSecureAuthenticationResponse authenticationResponse = new ThreeDSecureAuthenticationResponse();

        authenticationResponse.mSuccess = false;
        authenticationResponse.mException = exception;

        return authenticationResponse;
    }

    /**
     * @return If the authentication was completed
     */
    public boolean isSuccess() {
        return mSuccess;
    }

    /**
     * @return The {@link CardNonce} associated with the 3D Secure
     *         authentication
     */
    public CardNonce getCardNonce() {
        return mCardNonce;
    }

    /**
     * @return Possible errors that occurred during the authentication
     */
    public String getErrors() {
        return mErrors;
    }

    /**
     * @return Possible exception that occurred during the authentication
     */
    public String getException() {
        return mException;
    }

    /**
     * @return The 3D Secure info for the current {@link CardNonce} or
     * {@code null}
     */
    public ThreeDSecureInfo getThreeDSecureInfo() {
        return mThreeDSecureInfo;
    }

    public ThreeDSecureAuthenticationResponse() {}

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeByte(mSuccess ? (byte) 1 : (byte) 0);
        dest.writeParcelable(mCardNonce, flags);
        dest.writeString(mErrors);
        dest.writeString(mException);
        dest.writeParcelable(mThreeDSecureInfo, flags);
    }

    private ThreeDSecureAuthenticationResponse(Parcel in) {
        mSuccess = in.readByte() != 0;
        mCardNonce = in.readParcelable(CardNonce.class.getClassLoader());
        mErrors = in.readString();
        mException = in.readString();
        mThreeDSecureInfo = in.readParcelable(ThreeDSecureInfo.class.getClassLoader());
    }

    public static final Creator<ThreeDSecureAuthenticationResponse> CREATOR =
            new Creator<ThreeDSecureAuthenticationResponse>() {
                public ThreeDSecureAuthenticationResponse createFromParcel(Parcel source) {
                    return new ThreeDSecureAuthenticationResponse(source);
                }

                public ThreeDSecureAuthenticationResponse[] newArray(int size) {
                    return new ThreeDSecureAuthenticationResponse[size];
                }
            };
}

@@ -1594,145 +1594,129 @@
 DO: 
-We aren't currently getting a '
+3DS 1.0 has a %22
 success
-' value for 3DS 2.0%0A            // The below check for %22errors%22 can be removed once it is available
+%22 key, but 3DS 2.0 responses dont.%0A            // Waiting for the Gateway to send this success key.
 %0A   

Clarify TODO