package cc.softwarefactory.lokki.android.espresso;

import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.RecordedRequest;

import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtilsHC4;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

import cc.softwarefactory.lokki.android.R;
import cc.softwarefactory.lokki.android.espresso.utilities.MockJsonUtils;
import cc.softwarefactory.lokki.android.utils.Utils;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.clearText;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard;
import static android.support.test.espresso.action.ViewActions.typeText;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;

public class SignUpScreenTest extends NotLoggedInBaseTest {

    private void moveToSignUpScreen() {
        getActivity();
        onView(withText(R.string.continue_with_terms)).perform(click());
        onView(withText(R.string.i_agree)).perform(click());
    }

    private void enterEmail(String email) throws InterruptedException {
        onView(withId(R.id.email)).perform(clearText(), typeText(email), closeSoftKeyboard());

        // Without this we get "PerformException: Error performing 'single click' on view".
        // See https://code.google.com/p/android-test-kit/issues/detail?id=44
        Thread.sleep(100);
    }

    private void clickSignUpButton() {
        onView(withId(R.id.signup_button)).perform(click());
    }

    private String getRequest(String email) throws UnsupportedEncodingException {
        // TODO: ideal would be to set different device ids and languages and test if they're part
        // of the request, but let's just do this for now.
        String deviceId = Utils.getDeviceId();
        String language = Utils.getLanguage();

        List<NameValuePair> params = Arrays.<NameValuePair>asList(
                new BasicNameValuePair("email", email),
                new BasicNameValuePair("device_id", deviceId),
                new BasicNameValuePair("language", language)
        );

        return URLEncodedUtilsHC4.format(params, "utf8");
    }

    private void assertQueryStringEquals(String first, String second) {
        List<NameValuePair> firstList = URLEncodedUtilsHC4.parse(first, Charset.forName("utf8"));
        List<NameValuePair> secondList = URLEncodedUtilsHC4.parse(second, Charset.forName("utf8"));
        assertEquals(new HashSet(firstList), new HashSet(secondList));
    }

    public void testMapIsShownAfterSuccessfulSignup() throws InterruptedException, JSONException, UnsupportedEncodingException {
        moveToSignUpScreen();
        enterEmail("email@example.com");
        MockResponse loginOkResponse = new MockResponse();
        loginOkResponse.setBody(MockJsonUtils.getSignupResponse("123123", new String[]{}, new String[]{}, "3213123"));
        List<RecordedRequest> requests = mockDispatcher.setSignupResponse(loginOkResponse);
        clickSignUpButton();
        assertQueryStringEquals(getRequest("email@example.com"), requests.get(0).getUtf8Body());
        onView(withText(R.string.map)).check(matches(isDisplayed()));
    }

    public void testInvalidEmailGivesErrorMessage() throws InterruptedException, UnsupportedEncodingException {
        moveToSignUpScreen();
        enterEmail("invalid_email");
        MockResponse loginErrorResponse = new MockResponse();
        loginErrorResponse.setResponseCode(400);
        loginErrorResponse.setBody("Invalid email address.");
        List<RecordedRequest> requests = mockDispatcher.setSignupResponse(loginErrorResponse);
        clickSignUpButton();
        assertQueryStringEquals(getRequest("invalid_email"), requests.get(0).getUtf8Body());
        onView(withText(R.string.general_error)).check(matches(isDisplayed()));
    }

    public void testMessageIsShownIfAccountRequiresAuthorization() throws InterruptedException, UnsupportedEncodingException {
        moveToSignUpScreen();
        enterEmail("test@example.com");
        MockResponse loginNeedAuthorizationResponse = new MockResponse();
        loginNeedAuthorizationResponse.setResponseCode(401);
        List<RecordedRequest> requests = mockDispatcher.setSignupResponse(loginNeedAuthorizationResponse);
        String signupText = getInstrumentation().getTargetContext().getResources().getString(R.string.security_signup) + " test@example.com";
        clickSignUpButton();
        assertQueryStringEquals(getRequest("test@example.com"), requests.get(0).getUtf8Body());
        onView(withText(signupText)).check(matches(isDisplayed()));
    }

    public void testTypeYourEmailAddressIsShownWhenFieldIsEmptyAndTryingToSignup() throws InterruptedException {
        moveToSignUpScreen();
        enterEmail("");
        clickSignUpButton();
        onView(allOf(withId(R.id.email), withText(R.string.type_your_email_address))).check(matches(isDisplayed()));
    }
}

@@ -1650,21 +1650,27 @@
 te void 
-enter
+signUpUsing
 Email(St
@@ -1703,32 +1703,62 @@
 ptedException %7B%0A
+        moveToSignUpScreen();%0A
         onView(w
@@ -2038,53 +2038,8 @@
 0);%0A
-    %7D%0A%0A    private void clickSignUpButton() %7B
 %0A   
@@ -3243,79 +3243,8 @@
 n %7B%0A
-        moveToSignUpScreen();%0A        enterEmail(%22email@example.com%22);%0A
     
@@ -3505,32 +3505,33 @@
 kResponse);%0A
+%0A
         
 clickSignUpB
@@ -3518,34 +3518,52 @@
         
-clickSignUpButton(
+signUpUsingEmail(%22email@example.com%22
 );%0A     
@@ -3847,75 +3847,8 @@
 n %7B%0A
-        moveToSignUpScreen();%0A        enterEmail(%22invalid_email%22);%0A
     
@@ -4111,24 +4111,25 @@
 ponse);%0A
+%0A
         
 clickSig
@@ -4120,34 +4120,48 @@
         
-clickSignUpButton(
+signUpUsingEmail(%22invalid_email%22
 );%0A     
@@ -4466,78 +4466,8 @@
 n %7B%0A
-        moveToSignUpScreen();%0A        enterEmail(%22test@example.com%22);%0A
     
@@ -4736,48 +4736,8 @@
 t = 
-getInstrumentation().getTargetContext().
 getR
@@ -4806,24 +4806,25 @@
 e.com%22;%0A
+%0A
         
 clickSig
@@ -4815,34 +4815,51 @@
         
-clickSignUpButton(
+signUpUsingEmail(%22test@example.com%22
 );%0A     
@@ -5149,80 +5149,27 @@
     
-moveToSignUpScreen();%0A        enterEmail(%22%22);%0A        clickSignUpButton(
+signUpUsingEmail(%22%22
 );%0A 

Clean up signup tests