package com.braintreepayments.api;

import android.app.Activity;
import android.support.test.runner.AndroidJUnit4;

import com.braintreepayments.api.exceptions.AuthorizationException;
import com.braintreepayments.api.exceptions.InvalidArgumentException;
import com.braintreepayments.api.interfaces.BraintreeErrorListener;
import com.braintreepayments.api.interfaces.PaymentMethodNoncesUpdatedListener;
import com.braintreepayments.api.models.CardBuilder;
import com.braintreepayments.api.models.CardNonce;
import com.braintreepayments.api.models.PaymentMethodNonce;
import com.braintreepayments.api.test.BraintreeActivityTestRule;
import com.braintreepayments.api.test.TestActivity;
import com.braintreepayments.api.test.TestClientTokenBuilder;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.List;
import java.util.concurrent.CountDownLatch;

import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static com.braintreepayments.api.BraintreeFragmentTestUtils.tokenize;
import static com.braintreepayments.api.test.Assertions.assertIsANonce;
import static com.braintreepayments.testutils.CardNumber.VISA;
import static com.braintreepayments.testutils.TestTokenizationKey.TOKENIZATION_KEY;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;

@RunWith(AndroidJUnit4.class)
public class PaymentMethodTest {

    @Rule
    public final BraintreeActivityTestRule<TestActivity> mActivityTestRule =
            new BraintreeActivityTestRule<>(TestActivity.class);

    private Activity mActivity;

    @Before
    public void setUp() {
        mActivity = mActivityTestRule.getActivity();
    }

    @Test(timeout = 10000)
    public void getPaymentMethodNonces_getsPaymentMethodsFromServer() throws InterruptedException,
            InvalidArgumentException {
        final CountDownLatch latch = new CountDownLatch(1);
        final String clientToken = new TestClientTokenBuilder().build();
        BraintreeFragment fragment = BraintreeFragment.newInstance(mActivity, clientToken);
        getInstrumentation().waitForIdleSync();
        fragment.addListener(new PaymentMethodNoncesUpdatedListener() {
            @Override
            public void onPaymentMethodNoncesUpdated(List<PaymentMethodNonce> paymentMethodNonces) {
                assertEquals(1, paymentMethodNonces.size());
                assertIsANonce(paymentMethodNonces.get(0).getNonce());
                assertEquals("11", ((CardNonce) paymentMethodNonces.get(0)).getLastTwo());
                latch.countDown();
            }
        });
        tokenize(fragment, new CardBuilder()
                .cardNumber(VISA)
                .expirationMonth("04")
                .expirationYear("17"));

        PaymentMethod.getPaymentMethodNonces(fragment);

        latch.await();
    }

    @Test(timeout = 10000)
    public void getPaymentMethodNonces_failsWithATokenizationKey() throws InterruptedException,
            InvalidArgumentException {
        final CountDownLatch latch = new CountDownLatch(1);
        BraintreeFragment fragment = BraintreeFragment.newInstance(mActivity, TOKENIZATION_KEY);
        getInstrumentation().waitForIdleSync();
        fragment.addListener(new PaymentMethodNoncesUpdatedListener() {
            @Override
            public void onPaymentMethodNoncesUpdated(List<PaymentMethodNonce> paymentMethodNonces) {
                fail("getPaymentMethodNonces succeeded");
            }
        });
        fragment.addListener(new BraintreeErrorListener() {
            @Override
            public void onError(Exception error) {
                assertTrue(error instanceof AuthorizationException);
                assertEquals("Tokenization key authorization not allowed for this endpoint. Please use an authentication method with upgraded permissions",
                        error.getMessage());
                latch.countDown();
            }
        });
        tokenize(fragment, new CardBuilder()
                .cardNumber(VISA)
                .expirationMonth("04")
                .expirationYear("17"));

        PaymentMethod.getPaymentMethodNonces(fragment);

        latch.await();
    }
}

@@ -840,24 +840,86 @@
 r.RunWith;%0A%0A
+import java.text.SimpleDateFormat;%0Aimport java.util.Calendar;%0A
 import java.
@@ -2900,36 +2900,42 @@
 .expirationYear(
-%2217%22
+nextYear()
 ));%0A%0A        Pay
@@ -4274,12 +4274,18 @@
 ear(
-%2217%22
+nextYear()
 ));%0A
@@ -4370,11 +4370,252 @@
 );%0A    %7D
+%0A%0A    private String nextYear() %7B%0A        SimpleDateFormat twoDigitYear = new SimpleDateFormat(%22yy%22);%0A        Calendar cal = Calendar.getInstance();%0A        cal.add(Calendar.YEAR, 1);%0A%0A        return twoDigitYear.format(cal.getTime());%0A    %7D
 %0A%7D%0A

Replace hard coded year with next year