/*
 * oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
 *
 * Copyright (c) 2014, Gluu
 */

package org.gluu.oxauth.dev;

import java.util.Arrays;

import org.apache.http.client.CookieStore;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.gluu.oxauth.BaseTest;
import org.gluu.oxauth.client.AuthorizationRequest;
import org.gluu.oxauth.client.AuthorizationResponse;
import org.gluu.oxauth.client.AuthorizeClient;
import org.gluu.oxauth.client.TokenClient;
import org.gluu.oxauth.client.TokenResponse;
import org.gluu.oxauth.client.UserInfoClient;
import org.gluu.oxauth.client.UserInfoResponse;
import org.gluu.oxauth.model.common.Prompt;
import org.gluu.oxauth.model.common.ResponseType;
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

import junit.framework.Assert;

/**
 * @version August 9, 2017
 */
public class TestSessionWorkflow extends BaseTest {

    @Parameters({"userId", "userSecret", "clientId", "clientSecret", "redirectUri"})
    @Test
    public void test(final String userId, final String userSecret,
                     final String clientId, final String clientSecret,
                     final String redirectUri) throws Exception {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        try {
            CookieStore cookieStore = new BasicCookieStore();
            httpClient.setCookieStore(cookieStore);
            ApacheHttpClient43Engine clientExecutor = new ApacheHttpClient43Engine(httpClient);

            ////////////////////////////////////////////////
            //             TV side. Code 1                //
            ////////////////////////////////////////////////

            AuthorizationRequest authorizationRequest1 = new AuthorizationRequest(
                    Arrays.asList(ResponseType.CODE),
                    clientId,
                    Arrays.asList("openid", "profile", "email"),
                    redirectUri,
                    null);

            authorizationRequest1.setAuthUsername(userId);
            authorizationRequest1.setAuthPassword(userSecret);
            authorizationRequest1.getPrompts().add(Prompt.NONE);
            authorizationRequest1.setState("af0ifjsldkj");
            authorizationRequest1.setRequestSessionId(true);

            AuthorizeClient authorizeClient1 = new AuthorizeClient(authorizationEndpoint);
            authorizeClient1.setRequest(authorizationRequest1);
            AuthorizationResponse authorizationResponse1 = authorizeClient1.exec(clientExecutor);

            //        showClient(authorizeClient1, cookieStore);

            String code1 = authorizationResponse1.getCode();
            String sessionId = authorizationResponse1.getSessionId();
            Assert.assertNotNull("code1 is null", code1);
            Assert.assertNotNull("sessionId is null", sessionId);

            // TV sends the code to the Backend
            // We don't use httpClient and cookieStore during this call


            ////////////////////////////////////////////////
            //             Backend  1 side. Code 1        //
            ////////////////////////////////////////////////


            // Get the access token
            TokenClient tokenClient1 = new TokenClient(tokenEndpoint);
            TokenResponse tokenResponse1 = tokenClient1.execAuthorizationCode(code1, redirectUri, clientId, clientSecret);

            String accessToken1 = tokenResponse1.getAccessToken();
            Assert.assertNotNull("accessToken1 is null", accessToken1);

            // Get the user's claims
            UserInfoClient userInfoClient1 = new UserInfoClient(userInfoEndpoint);
            UserInfoResponse userInfoResponse1 = userInfoClient1.execUserInfo(accessToken1);

            Assert.assertTrue("userInfoResponse1.getStatus() is not 200", userInfoResponse1.getStatus() == 200);
            //        System.out.println(userInfoResponse1.getEntity());


            ////////////////////////////////////////////////
            //             TV side. Code 2                //
            ////////////////////////////////////////////////

            AuthorizationRequest authorizationRequest2 = new AuthorizationRequest(
                    Arrays.asList(ResponseType.CODE),
                    clientId,
                    Arrays.asList("openid", "profile", "email"),
                    redirectUri,
                    null);

            authorizationRequest2.getPrompts().add(Prompt.NONE);
            authorizationRequest2.setState("af0ifjsldkj");
            authorizationRequest2.setSessionId(sessionId);

            AuthorizeClient authorizeClient2 = new AuthorizeClient(authorizationEndpoint);
            authorizeClient2.setRequest(authorizationRequest2);
            AuthorizationResponse authorizationResponse2 = authorizeClient2.exec(clientExecutor);

            //        showClient(authorizeClient2, cookieStore);

            String code2 = authorizationResponse2.getCode();
            Assert.assertNotNull("code2 is null", code2);


            // TV sends the code to the Backend
            // We don't use httpClient and cookieStore during this call


            ////////////////////////////////////////////////
            //             Backend  2 side. Code 2        //
            ////////////////////////////////////////////////


            // Get the access token
            TokenClient tokenClient2 = new TokenClient(tokenEndpoint);
            TokenResponse tokenResponse2 = tokenClient2.execAuthorizationCode(code2, redirectUri, clientId, clientSecret);

            String accessToken2 = tokenResponse2.getAccessToken();
            Assert.assertNotNull("accessToken2 is null", accessToken2);

            // Get the user's claims
            UserInfoClient userInfoClient2 = new UserInfoClient(userInfoEndpoint);
            UserInfoResponse userInfoResponse2 = userInfoClient2.execUserInfo(accessToken2);

            Assert.assertTrue("userInfoResponse1.getStatus() is not 200", userInfoResponse2.getStatus() == 200);
            //        System.out.println(userInfoResponse2.getEntity());
        } finally {
            if (httpClient != null) {
                httpClient.getConnectionManager().shutdown();
            }
        }
    }

    @Parameters({"userId", "userSecret", "clientId", "clientSecret", "redirectUri"})
    //@Test
    public void stressTest(final String userId, final String userSecret,
                           final String clientId, final String clientSecret,
                           final String redirectUri) throws Exception {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 500; i++) {
            System.out.println(i);
            test(userId, userSecret, clientId, clientSecret, redirectUri);
        }
        long endTime = System.currentTimeMillis();
        System.out.println((endTime - startTime) / 1000);
    }
}