/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.sling.auth.form.it;

import static org.apache.sling.testing.paxexam.SlingOptions.slingScriptingSightly;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.factoryConfiguration;
import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.newConfiguration;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.List;

import javax.inject.Inject;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.cookie.Cookie;
import org.apache.http.cookie.CookieOrigin;
import org.apache.http.cookie.CookieSpec;
import org.apache.http.cookie.MalformedCookieException;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.DefaultCookieSpec;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerClass;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;

/**
 * integration tests to verify fix for SLING-10290
 */
@RunWith(PaxExam.class)
@ExamReactorStrategy(PerClass.class)
public class SLING10290IT extends AuthFormTestSupport {

    @Inject
    private ConfigurationAdmin cm;

    private static final String COOKIE_SLING_FORMAUTH = "sling.formauth";
    private static final String HEADER_SET_COOKIE = "Set-Cookie";

    private URI baseServerUri;
    private HttpClientContext httpContext;
    private CloseableHttpClient httpClient;

    @Override
    protected Option[] additionalOptions() throws IOException {
        // create a tinybundle that contains a test script
        final List<String> resourcePaths = Arrays.asList("/apps/sling/OrderedFolder/SLING10290IT.html");
        final String bundleResourcesHeader = String.join(",", resourcePaths);
        final Option bundle = buildBundleResourcesBundle(bundleResourcesHeader, resourcePaths);

        return new Option[]{
            // add sightly support for the test script
            slingScriptingSightly(),

            // add the test script tinybundle
            bundle,

            // change the formauth timeout to 1 minute so we don't have to wait a long
            //   time for the testRefreshCookieOnRequestAfterHalfExpirationDuration test
            newConfiguration("org.apache.sling.auth.form.FormAuthenticationHandler")
                .put("form.auth.timeout", "1")
            .asOption(),

            // enable the healthcheck configuration for checking when the server is ready to
            //  receive http requests.  (adapted from the starter healthcheck.json configuration)
            factoryConfiguration("org.apache.felix.hc.generalchecks.FrameworkStartCheck")
                .put("hc.tags", new String[] {"systemalive"})
                .put("targetStartLevel", 5)
                .asOption(),
            factoryConfiguration("org.apache.felix.hc.generalchecks.ServicesCheck")
                .put("hc.tags", new String[] {"systemalive"})
                .put("services.list", new String[] {
                        "org.apache.sling.jcr.api.SlingRepository",
                        "org.apache.sling.engine.auth.Authenticator",
                        "org.apache.sling.api.resource.ResourceResolverFactory",
                        "org.apache.sling.api.servlets.ServletResolver",
                        "javax.script.ScriptEngineManager"
                })
                .asOption(),
            factoryConfiguration("org.apache.felix.hc.generalchecks.BundlesStartedCheck")
                .put("hc.tags", new String[] {"bundles"})
                .asOption(),
            factoryConfiguration("org.apache.sling.jcr.contentloader.hc.BundleContentLoadedCheck")
                .put("hc.tags", new String[] {"bundles"})
                .asOption(),
        };
    }

    @Before
    public void before() throws IOException, URISyntaxException {
        // wait for the health checks to be OK
        waitForServerReady(Duration.ofMinutes(1).toMillis(), 500);

        // calculate the address of the http server
        baseServerUri = getBaseServerUri();
        assertNotNull(baseServerUri);

        // prepare the http client for the test user
        httpContext = HttpClientContext.create();
        httpContext.setCookieStore(new BasicCookieStore());
        httpClient = HttpClients.custom()
                .disableRedirectHandling()
                .build();
    }

    @After
    public void after() throws IOException {
        // close/cleanup the test user http client
        if (httpClient != null) {
            httpClient.close();
            httpClient = null;
        }

        // clear out other state
        httpContext = null;
        baseServerUri = null;
    }

    /**
     * Verify that the formauth cookie is sent appropriately after login
     */
    @Test
    public void testSetCookieOnFirstRequestAfterLogin() throws MalformedCookieException, IOException {
        doFormsLogin();
    }

    /**
     * Verify that the formauth cookie is not re-sent on each request after login
     */
    @Test
    public void testNoSetCookieOnSecondRequestAfterLogin() throws MalformedCookieException, IOException {
        // 1. login as the test user
        doFormsLogin();

        // 2. do another request
        HttpGet request = new HttpGet(whoamiUri());
        try (CloseableHttpResponse response = httpClient.execute(request, httpContext)) {
            assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode());
            Cookie parsedFormauthCookie = parseFormAuthCookieFromHeaders(response);
            assertNull("Did not expect a formauth cookie in the response", parsedFormauthCookie);
        }
    }

    /**
     * Verify that the formauth cookie is refreshed on the first request after half the session duration
     * has occurred
     */
    @Test
    public void testRefreshCookieOnRequestAfterHalfExpirationDuration() throws InterruptedException, MalformedCookieException, IOException {
        // 1. login as the test user
        doFormsLogin();

        // 2. wait for half the session timeout expiration duration
        Thread.sleep((Duration.ofMinutes(1).toMillis() / 2) + 1); // NOSONAR

        // 3. do another request to trigger the cookie refresh
        HttpGet request = new HttpGet(whoamiUri());
        try (CloseableHttpResponse response = httpClient.execute(request, httpContext)) {
            assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode());
            Cookie parsedFormauthCookie = parseFormAuthCookieFromHeaders(response);
            assertNotNull("Expected a refreshed formauth cookie in the response", parsedFormauthCookie);
        }

        // 4. do another request to verify that subsequent request after
        //    the cookie refresh do not send an additional formauth cookie
        try (CloseableHttpResponse response = httpClient.execute(request, httpContext)) {
            assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode());
            Cookie parsedFormauthCookie2 = parseFormAuthCookieFromHeaders(response);
            assertNull("Did not expect a formauth cookie in the response", parsedFormauthCookie2);
        }
    }

    /**
     * Calculate the base server URI from the current configuration of the
     * httpservice
     */
    private URI getBaseServerUri() throws IOException, URISyntaxException {
        assertNotNull(cm);
        Configuration httpServiceConfiguration = cm.getConfiguration("org.apache.felix.http");
        Dictionary<String, Object> properties = httpServiceConfiguration.getProperties();

        String host;
        Object hostObj = properties.get("org.apache.felix.http.host");
        if (hostObj == null) {
            host = "localhost";
        } else {
            assertTrue(hostObj instanceof String);
            host = (String)hostObj;
        }
        assertNotNull(host);

        String scheme = null;
        Object portObj = null;
        Object httpsEnableObj = properties.get("org.apache.felix.https.enable");
        if ("true".equals(httpsEnableObj)) {
            scheme = "https";
            portObj = properties.get("org.osgi.service.http.port.secure");
        } else {
            Object httpEnableObj = properties.get("org.apache.felix.http.enable");
            if (httpEnableObj == null || "true".equals(httpEnableObj)) {
                scheme = "http";
                portObj = properties.get("org.osgi.service.http.port");
            } else {
                fail("Expected either http or https to be enabled");
            }
        }
        int port = -1;
        if (portObj instanceof Number) {
            port = ((Number)portObj).intValue();
        }
        assertTrue(port > 0);

        return new URI(String.format("%s://%s:%d", scheme, host, port));
    }

    /**
     * @return the address of the whoami script
     */
    private String whoamiUri() {
        return String.format("%s/content.SLING10290IT.html", baseServerUri);
    }

    /**
     * Perform the http calls to login the test user via the forms based login
     */
    private void doFormsLogin() throws MalformedCookieException, IOException {
        // before login, there should be no formauth cookie in the cookie store
        Cookie formauthCookie = getFormAuthCookieFromCookieStore();
        assertNull("Did not expect formauth cookie in the cookie store", formauthCookie);

        // verify that the script shows us as not logged in
        HttpGet whoamiRequest = new HttpGet(whoamiUri());
        try (CloseableHttpResponse whoamiResponse = httpClient.execute(whoamiRequest, httpContext)) {
            assertEquals(HttpServletResponse.SC_OK, whoamiResponse.getStatusLine().getStatusCode());
            String content = EntityUtils.toString(whoamiResponse.getEntity());
            assertTrue(content.contains("whoAmI"));
            assertTrue(content.contains("anonymous"));
        }

        // send the form login request
        List<NameValuePair> parameters = new ArrayList<>();
        parameters.add(new BasicNameValuePair("j_username", FORM_AUTH_VERIFY_USER));
        parameters.add(new BasicNameValuePair("j_password", FORM_AUTH_VERIFY_PWD));
        parameters.add(new BasicNameValuePair("_charset_", StandardCharsets.UTF_8.name()));
        parameters.add(new BasicNameValuePair("resource", "/content.SLING10290IT.html"));
        HttpPost request = new HttpPost(String.format("%s/j_security_check", baseServerUri));
        request.setEntity(new UrlEncodedFormEntity(parameters));
        Header locationHeader = null; 
        try (CloseableHttpResponse response = httpClient.execute(request, httpContext)) {
            assertEquals(HttpServletResponse.SC_MOVED_TEMPORARILY, response.getStatusLine().getStatusCode());
            locationHeader = response.getFirstHeader("Location");

            // verify that the expected set-cookie header arrived
            Cookie parsedFormauthCookie = parseFormAuthCookieFromHeaders(response);
            assertNotNull("Expected a formauth cookie in the response", parsedFormauthCookie);
        }

        // after login, there should be now be a cookie in the cookie store
        Cookie formauthCookie2 = getFormAuthCookieFromCookieStore();
        assertNotNull("Expected a formauth cookie in the cookie store", formauthCookie2);

        // and then follow the redirect
        assertNotNull("Expected a 'Location' header", locationHeader);
        // verify that the script shows us logged in as the test user
        HttpGet followedRequest = new HttpGet(locationHeader.getValue());
        try (CloseableHttpResponse followedResponse = httpClient.execute(followedRequest, httpContext)) {
            assertEquals(HttpServletResponse.SC_OK, followedResponse.getStatusLine().getStatusCode());
            String content = EntityUtils.toString(followedResponse.getEntity());
            assertTrue(content.contains("whoAmI"));
            assertTrue(content.contains(FORM_AUTH_VERIFY_USER));

            // there should be no new formauth cookie on the followed response
            Cookie parsedFormauthCookie2 = parseFormAuthCookieFromHeaders(followedResponse);
            assertNull("Did not expect a formauth cookie in the response", parsedFormauthCookie2);
        }
    }

    /**
     * Retrieve the formauth cookie from the cookie store
     * 
     * @return the formauth cookie or null if not found
     */
    private Cookie getFormAuthCookieFromCookieStore() {
        Cookie formauthCookie = null;
        List<Cookie> cookies = httpContext.getCookieStore().getCookies();
        if (cookies != null) {
            for (Cookie c : cookies) {
                if (COOKIE_SLING_FORMAUTH.equals(c.getName())) {
                    formauthCookie = c;
                }
            }
        }
        return formauthCookie;
    }

    /**
     * Parse the formauth cookie out of the headers sent on the response
     *
     * @param response the response from the http request
     * @return the found cookie or null if not found
     */
    private Cookie parseFormAuthCookieFromHeaders(HttpResponse response) throws MalformedCookieException {
        Header [] cookieHeaders = response.getHeaders(HEADER_SET_COOKIE);
        assertNotNull(cookieHeaders);

        Cookie parsedFormauthCookie = null;
        CookieSpec cookieSpec = new DefaultCookieSpec();
        CookieOrigin origin = new CookieOrigin(baseServerUri.getHost(), baseServerUri.getPort(),
                baseServerUri.getPath(), "https".equals(baseServerUri.getScheme()));
        for (Header cookieHeader : cookieHeaders) {
            List<Cookie> parsedCookies = cookieSpec.parse(cookieHeader, origin);
            for (Cookie c : parsedCookies) {
                if (COOKIE_SLING_FORMAUTH.equals(c.getName())) {
                    if (parsedFormauthCookie != null) {
                        fail(String.format("Did not expect more than one %s cookie", c.getName()));
                    }
                    parsedFormauthCookie = c;
                }
            }
        }
        return parsedFormauthCookie;
    }

}
