package org.pac4j.cas.client.rest;

import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.junit.Test;
import org.pac4j.cas.credentials.authenticator.CasRestAuthenticator;
import org.pac4j.cas.profile.HttpTGTProfile;
import org.pac4j.cas.credentials.CasCredentials;
import org.pac4j.cas.profile.CasProfile;
import org.pac4j.core.context.MockWebContext;
import org.pac4j.core.exception.RequiresHttpAction;
import org.pac4j.core.exception.TechnicalException;
import org.pac4j.core.util.TestsConstants;
import org.pac4j.core.credentials.UsernamePasswordCredentials;
import org.pac4j.core.credentials.authenticator.Authenticator;
import org.pac4j.core.credentials.authenticator.LocalCachingAuthenticator;

import java.util.Base64;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.*;

/**
 * Tests the {@link CasRestBasicAuthClient} and {@link CasRestFormClient}.
 *
 * @author Misagh Moayyed
 * @since 1.8.0
 */
public final class CasRestClientIT implements TestsConstants {

    private final static String CAS_PREFIX_URL = "http://casserverpac4j.herokuapp.com/";

    @Test
    public void testRestForm() throws RequiresHttpAction {
        internalTestRestForm(new CasRestAuthenticator(CAS_PREFIX_URL));
    }

    @Test
    public void testRestFormWithCaching() throws RequiresHttpAction {
        internalTestRestForm(new LocalCachingAuthenticator<>(new CasRestAuthenticator(CAS_PREFIX_URL), 100, 100, TimeUnit.SECONDS));
    }

    private void internalTestRestForm(final Authenticator authenticator) throws RequiresHttpAction {
        final CasRestFormClient client = new CasRestFormClient();
        client.setAuthenticator(authenticator);

        final MockWebContext context = MockWebContext.create();
        context.addRequestParameter(client.getUsernameParameter(), USERNAME);
        context.addRequestParameter(client.getPasswordParameter(), USERNAME);

        final UsernamePasswordCredentials credentials = client.getCredentials(context);
        final HttpTGTProfile profile = client.getUserProfile(credentials, context);
        assertEquals(USERNAME, profile.getId());
        assertNotNull(profile.getTicketGrantingTicketId());

        final CasCredentials casCreds = client.requestServiceTicket(PAC4J_BASE_URL, profile);
        final CasProfile casProfile = client.validateServiceTicket(PAC4J_BASE_URL, casCreds);
        assertNotNull(casProfile);
        assertEquals(USERNAME, casProfile.getId());
    }

    @Test
    public void testRestBasic() throws RequiresHttpAction {
        internalTestRestBasic(new CasRestBasicAuthClient(CAS_PREFIX_URL, VALUE, NAME));
    }

    @Test
    public void testRestBasicWithCas20TicketValidator() throws RequiresHttpAction {
        final CasRestAuthenticator authenticator = new CasRestAuthenticator(CAS_PREFIX_URL);
        authenticator.setTicketValidator(new Cas20ServiceTicketValidator(CAS_PREFIX_URL));
        internalTestRestBasic(new CasRestBasicAuthClient(authenticator, VALUE, NAME));
    }

    private void internalTestRestBasic(final CasRestBasicAuthClient client) throws RequiresHttpAction {
        final MockWebContext context = MockWebContext.create();
        final String token = USERNAME + ":" + USERNAME;
        context.addRequestHeader(VALUE, NAME + Base64.getEncoder().encodeToString(token.getBytes()));

        final UsernamePasswordCredentials credentials = client.getCredentials(context);
        final HttpTGTProfile profile = client.getUserProfile(credentials, context);
        assertEquals(USERNAME, profile.getId());
        assertNotNull(profile.getTicketGrantingTicketId());

        final CasCredentials casCreds = client.requestServiceTicket(PAC4J_BASE_URL, profile);
        final CasProfile casProfile = client.validateServiceTicket(PAC4J_BASE_URL, casCreds);
        assertNotNull(casProfile);
        assertEquals(USERNAME, casProfile.getId());
        client.destroyTicketGrantingTicket(profile);

        try {
            client.requestServiceTicket(PAC4J_BASE_URL, profile);
            fail("shoud fail");
        } catch (final TechnicalException e) {
            assertEquals("Service ticket request for `<HttpTGTProfile> | id: username | attributes: {} | roles: [] | permissions: [] | isRemembered: false |` failed: (404) Not Found", e.getMessage());
        }
    }
}

@@ -2458,24 +2458,83 @@
 e.getId());%0A
+        assertTrue(casProfile.getAttributes().size() %3E 0);%0A
     %7D%0A%0A    @
@@ -2675,32 +2675,35 @@
 RL, VALUE, NAME)
+, 3
 );%0A    %7D%0A%0A    @T
@@ -3058,16 +3058,19 @@
 E, NAME)
+, 0
 );%0A    %7D
@@ -3145,16 +3145,34 @@
 t client
+, int nbAttributes
 ) throws
@@ -3965,32 +3965,103 @@
 ofile.getId());%0A
+        assertEquals(nbAttributes, casProfile.getAttributes().size());%0A
         client.d

test nb attributes