/*
 * 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.felix.hc.api.FormattingResultLog.msHumanReadable;
import static org.apache.sling.testing.paxexam.SlingOptions.awaitility;
import static org.apache.sling.testing.paxexam.SlingOptions.slingQuickstartOakTar;
import static org.apache.sling.testing.paxexam.SlingOptions.versionResolver;
import static org.awaitility.Awaitility.await;
import static org.junit.Assert.assertNotNull;
import static org.ops4j.pax.exam.CoreOptions.composite;
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.streamBundle;
import static org.ops4j.pax.exam.CoreOptions.vmOption;
import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.factoryConfiguration;
import static org.ops4j.pax.tinybundles.core.TinyBundles.withBnd;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;

import org.apache.felix.hc.api.Result;
import org.apache.felix.hc.api.ResultLog;
import org.apache.felix.hc.api.execution.HealthCheckExecutionResult;
import org.apache.felix.hc.api.execution.HealthCheckExecutor;
import org.apache.felix.hc.api.execution.HealthCheckSelector;
import org.apache.sling.testing.paxexam.TestSupport;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.options.ModifiableCompositeOption;
import org.ops4j.pax.exam.options.extra.VMOption;
import org.ops4j.pax.tinybundles.core.TinyBundle;
import org.ops4j.pax.tinybundles.core.TinyBundles;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AuthFormTestSupport extends TestSupport {
    private static final String BUNDLE_SYMBOLICNAME = "TEST-CONTENT-BUNDLE";
    private static final String SLING_BUNDLE_RESOURCES_HEADER = "Sling-Bundle-Resources";

    protected static final String FORM_AUTH_VERIFY_USER = "form-auth-user";
    protected static final String FORM_AUTH_VERIFY_PWD = "testing";

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @Inject
    private HealthCheckExecutor hcExecutor;


    @Configuration
    public Option[] configuration() throws IOException {
        return options(
            composite(
                super.baseConfiguration(),
                vmOption(System.getProperty("pax.vm.options")),
                optionalRemoteDebug(),
                slingQuickstart(),
                testBundle("bundle.filename"),
                // testing - add a user to use to login and verify the content loading has happened
                factoryConfiguration("org.apache.sling.jcr.repoinit.RepositoryInitializer")
                    .put("scripts", new String[] {
                            "create user " + FORM_AUTH_VERIFY_USER + " with password " + FORM_AUTH_VERIFY_PWD +"\n"
                            })
                    .asOption(),
                junitBundles(),
                awaitility()
            ).add(
                additionalOptions()
            ).remove(
                // remove our bundle under test to avoid duplication
                mavenBundle().groupId("org.apache.sling").artifactId("org.apache.sling.auth.form").version(versionResolver)
            )
        );
    }

    protected Option[] additionalOptions() throws IOException {
        return new Option[]{};
    }

    protected Option slingQuickstart() {
        final String workingDirectory = workingDirectory();
        final int httpPort = findFreePort();
        return composite(
            slingQuickstartOakTar(workingDirectory, httpPort)
        );
    }

    public String getTestFileUrl(String path) {
        return getClass().getResource(path).toExternalForm();
    }

    /**
     * Optionally configure remote debugging on the port supplied by the "debugPort"
     * system property.
     */
    protected ModifiableCompositeOption optionalRemoteDebug() {
        VMOption option = null;
        String property = System.getProperty("debugPort");
        if (property != null) {
            option = vmOption(String.format("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=%s", property));
        }
        return composite(option);
    }

    /**
     * Wait for the health check to be ok
     * 
     * @param timeoutMsec the max time to wait for the health check to be ok
     * @param nextIterationDelay the sleep time between the check attempts
     */
    protected void waitForServerReady(long timeoutMsec, long nextIterationDelay) {
        // retry until the exec call returns true and doesn't throw any exception
        await().atMost(timeoutMsec, TimeUnit.MILLISECONDS)
                .pollInterval(nextIterationDelay, TimeUnit.MILLISECONDS)
                .until(this::doHealthCheck); 
    }

    /**
     * @return true if health checks are ok
     */
    protected boolean doHealthCheck() throws IOException {
        boolean isOk = true;
        logger.info("Performing health check");
        HealthCheckSelector hcs = HealthCheckSelector.tags("systemalive");
        List<HealthCheckExecutionResult> results = hcExecutor.execute(hcs);
        logger.info("systemalive health check got {} results", results.size());
        isOk &= !results.isEmpty();
        for (final HealthCheckExecutionResult exR : results) {
            final Result r = exR.getHealthCheckResult();
            if (logger.isInfoEnabled()) {
                logger.info("systemalive health check: {}", toHealthCheckResultInfo(exR, false));
            }
            isOk &= r.isOk();
            if (!isOk) {
                break; // found a failure so stop checking further
            }
        }

        if (isOk) {
            hcs = HealthCheckSelector.tags("bundles");
            results = hcExecutor.execute(hcs);
            logger.info("bundles health check got {} results", results.size());
            isOk &= !results.isEmpty();
            for (final HealthCheckExecutionResult exR : results) {
                final Result r = exR.getHealthCheckResult();
                if (logger.isInfoEnabled()) {
                    logger.info("bundles health check: {}", toHealthCheckResultInfo(exR, false));
                }
                isOk &= r.isOk();
                if (!isOk) {
                    break; // found a failure so stop checking further
                }
            }
        }
        return isOk;
    }

    /**
     * Produce a human readable report of the health check results that is suitable for
     * debugging or writing to a log
     */
    protected String toHealthCheckResultInfo(final HealthCheckExecutionResult exResult, final boolean debug)  throws IOException {
        String value = null;
        try (StringWriter resultWriter = new StringWriter(); BufferedWriter writer = new BufferedWriter(resultWriter)) {
            final Result result = exResult.getHealthCheckResult();

            writer.append('"').append(exResult.getHealthCheckMetadata().getTitle()).append('"');
            writer.append(" result is: ").append(result.getStatus().toString());
            writer.newLine();
            writer.append("   Finished: ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(exResult.getFinishedAt()) + " after "
                    + msHumanReadable(exResult.getElapsedTimeInMs()));

            for (final ResultLog.Entry e : result) {
                if (!debug && e.isDebug()) {
                    continue;
                }
                writer.newLine();
                writer.append("   ");
                writer.append(e.getStatus().toString());
                writer.append(' ');
                writer.append(e.getMessage());
                if (e.getException() != null) {
                    writer.append(" ");
                    writer.append(e.getException().toString());
                }
            }
            writer.flush();
            value = resultWriter.toString();
        }
        return value;
    }

    /**
     * Add content to our test bundle
     */
    protected void addContent(final TinyBundle bundle, String resourcePath) throws IOException {
        String pathInBundle = resourcePath;
        resourcePath = "/content" + resourcePath;
        try (final InputStream is = getClass().getResourceAsStream(resourcePath)) {
            assertNotNull("Expecting resource to be found:" + resourcePath, is);
            logger.info("Adding resource to bundle, path={}, resource={}", pathInBundle, resourcePath);
            bundle.add(pathInBundle, is);
        }
    }

    /**
     * Build a test bundle containing the specified bundle resources
     * 
     * @param header the value for the {@link #SLING_BUNDLE_RESOURCES_HEADER} header
     * @param content the collection of files to embed in the tinybundle
     * @return the tinybundle Option
     */
    protected Option buildBundleResourcesBundle(final String header, final Collection<String> content) throws IOException {
        final TinyBundle bundle = TinyBundles.bundle();
        bundle.set(Constants.BUNDLE_SYMBOLICNAME, BUNDLE_SYMBOLICNAME);
        bundle.set(SLING_BUNDLE_RESOURCES_HEADER, header);
        bundle.set("Require-Capability", "osgi.extender;filter:=\"(&(osgi.extender=org.apache.sling.bundleresource)(version<=1.1.0)(!(version>=2.0.0)))\"");

        for (final String entry : content) {
            addContent(bundle, entry);
        }
        return streamBundle(
            bundle.build(withBnd())
        ).start();
    }

}
