/*
 * 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.karaf.tests.bootstrap;

import java.io.Reader;
import java.io.StringReader;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import javax.inject.Inject;
import javax.jcr.Credentials;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;
import javax.jcr.observation.ObservationManager;
import javax.jcr.query.Query;

import org.apache.jackrabbit.commons.cnd.CndImporter;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.karaf.testing.KarafTestSupport;
import org.junit.Ignore;
import org.junit.Test;
import org.ops4j.pax.exam.util.Filter;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public abstract class AbstractSlingQuickstartOakTestSupport extends KarafTestSupport {

    @Inject
    @Filter(timeout = 300000)
    public SlingRepository slingRepository;

    @Inject
    @Filter(timeout = 300000)
    public ResourceResolverFactory resourceResolverFactory;

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

    public AbstractSlingQuickstartOakTestSupport() {
    }

    @Test
    public void testSlingRepository() throws Exception {
        assertNotNull(slingRepository);
    }

    // see org.apache.sling.jcr.repository.it.CommonTests

    private final AtomicInteger uniqueNameCounter = new AtomicInteger();
    protected static final Integer TEST_SCALE = Integer.getInteger("test.scale", 1);

    public static final String I18N_MESSAGE_CND =
        "<sling = 'http://sling.apache.org/jcr/sling/1.0'>\n"
            + "[mix:language]\n"
            + "mixin\n"
            + "- jcr:language (string)\n"
            + "\n"
            + "[sling:Message]\n"
            + "mixin\n"
            + "- sling:key (string)\n"
            + "- sling:message (undefined)\n"
            + "\n"
            + "[sling:MessageEntry] > nt:hierarchyNode, sling:Message\n"
        ;

    protected class JcrEventsCounter implements EventListener {
        private final Session s;
        private int jcrEventsCounter;

        public JcrEventsCounter() throws RepositoryException {
            s = slingRepository.loginAdministrative(null);
            final ObservationManager om = s.getWorkspace().getObservationManager();
            final int eventTypes = 255; // not sure if that's a recommended value, but common
            final boolean deep = true;
            final String [] uuid = null;
            final String [] nodeTypeNames = new String [] { "mix:language", "sling:Message" };
            final boolean noLocal = true;
            final String root = "/";
            om.addEventListener(this, eventTypes, root, deep, uuid, nodeTypeNames, noLocal);
        }

        void close() {
            s.logout();
        }

        @Override
        public void onEvent(EventIterator it) {
            while(it.hasNext()) {
                it.nextEvent();
                jcrEventsCounter++;
            }
        }

        int get() {
            return jcrEventsCounter;
        }
    }

    /** Simple Retry loop for tests */
    public abstract class Retry {

        public Retry(int timeoutMsec) {
            final long timeout = System.currentTimeMillis() + timeoutMsec;
            Throwable lastT = null;
            while(System.currentTimeMillis() < timeout) {
                try {
                    lastT = null;
                    exec();
                    break;
                } catch(Throwable t) {
                    lastT = t;
                }
            }

            if(lastT != null) {
                fail("Failed after " + timeoutMsec + " msec: " + lastT);
            }
        }

        protected abstract void exec() throws Exception;
    }

    /** Verify that admin can create and retrieve a node of the specified type.
     * @return the path of the test node that was created.
     */
    private String assertCreateRetrieveNode(String nodeType) throws RepositoryException {
        Session s = slingRepository.loginAdministrative(null);
        try {
            final Node root = s.getRootNode();
            final Node content = root.getNodes("content").nextNode();
            final String name = uniqueName("assertCreateRetrieveNode");
            final String propName = "PN_" + name;
            final String propValue = "PV_" + name;
            final Node child = nodeType == null ? content.addNode(name) : content.addNode(name, nodeType);
            child.setProperty(propName, propValue);
            child.setProperty("foo", child.getPath());
            s.save();
            s.logout();
            s = slingRepository.loginAdministrative(null);
            final Node n = s.getNode("/content/" + name);
            assertNotNull(n);
            assertEquals(propValue, n.getProperty(propName).getString());
            return n.getPath();
        } finally {
            s.logout();
        }
    }

    protected String uniqueName(String hint) {
        return hint + "_" + uniqueNameCounter.incrementAndGet() + "_" + System.currentTimeMillis();
    }

    @Test
    public void testRepositoryPresent() {
        assertNotNull(slingRepository);
    }

    @Test
    public void testLoginAdministrative() throws RepositoryException {
        final Session s = slingRepository.loginAdministrative(null);
        assertNotNull(s);
        s.logout();
    }

    @Test
    public void testExplicitAdminLogin() throws RepositoryException {
        final Credentials creds = new SimpleCredentials("admin", "admin".toCharArray());
        slingRepository.login(creds).logout();
    }

    @Test(expected=RepositoryException.class)
    public void testWrongLogin() throws RepositoryException {
        final Credentials creds = new SimpleCredentials("badName", "badPAssword".toCharArray());
        slingRepository.login(creds);
    }

    @Test
    public void testAnonymousLoginA() throws RepositoryException {
        final Session s = slingRepository.login();
        assertNotNull(s);
        s.logout();
    }

    @Test
    public void testAnonymousLoginB() throws RepositoryException {
        final Session s = slingRepository.login(null, null);
        assertNotNull(s);
        s.logout();
    }

    @Test
    public void testCreateRetrieveNode() throws RepositoryException {
        assertCreateRetrieveNode(null);
    }

    @Test
    public void testCreateRetrieveSlingFolder() throws RepositoryException {
        assertCreateRetrieveNode("sling:Folder");
    }

    @Test
    public void testAnonymousHasReadAccess() throws RepositoryException {
        final String path = assertCreateRetrieveNode(null);
        final Session s = slingRepository.login();
        try {
            assertTrue("Expecting anonymous to see " + path, s.itemExists(path));
            final Node n = s.getNode(path);
            assertEquals("Expecting anonymous to see the foo property", path, n.getProperty("foo").getString());
        } finally {
            s.logout();
        }
    }

    @Test
    public void testSqlQuery() throws RepositoryException {
        final Session s = slingRepository.loginAdministrative(null);
        final String id = "ID_" + System.currentTimeMillis();
        final String propName = "PROP_" + id;
        final String value = "VALUE_" + id;
        try {
            final int N_NODES = 100;
            for(int i=0 ; i < N_NODES; i++) {
                final Node root = s.getRootNode();
                root.addNode(id + i).setProperty(propName, value);
            }
            s.save();

            final String stmt = "SELECT * FROM nt:base WHERE " + propName + " IS NOT NULL";

            @SuppressWarnings("deprecation")
            final Query q = s.getWorkspace().getQueryManager().createQuery(stmt, Query.SQL);

            final NodeIterator it = q.execute().getNodes();
            int count = 0;
            while(it.hasNext()) {
                it.next();
                count++;
            }
            assertEquals("Expected " + N_NODES + " result for query " + stmt, N_NODES, count);
        } finally {
            s.logout();
        }
    }

    @Test
    public void testXpathQueryWithMixin() throws RepositoryException {
        Session s = slingRepository.loginAdministrative(null);
        try {
            final String path = "XPATH_QUERY_" + System.currentTimeMillis();
            final String absPath = "/" + path;
            final Node n = s.getRootNode().addNode(path);
            n.addMixin("mix:title");
            s.save();

            final String statement = "/jcr:root//element(*, mix:title)";
            @SuppressWarnings("deprecation")
            final Query q = s.getWorkspace().getQueryManager().createQuery(statement, Query.XPATH);
            final NodeIterator it = q.execute().getNodes();
            assertTrue("Expecting a non-empty result", it.hasNext());
            boolean found = false;
            while(it.hasNext()) {
                if(it.nextNode().getPath().equals(absPath)) {
                    found = true;
                    break;
                }
            }
            assertTrue("Expecting test node " + absPath + " to be found", found);
        } finally {
            s.logout();
        }
    }

    @Test
    public void testSingleValueInputStream() throws RepositoryException {
        Session s = slingRepository.loginAdministrative(null);
        try {
            final String path = getClass().getSimpleName() + System.currentTimeMillis();
            final Node child = s.getRootNode().addNode(path);
            final Property p = child.setProperty("foo", "bar");
            s.save();
            assertNotNull(p.getBinary().getStream());
        } finally {
            s.logout();
        }

    }

    @Test
    public void testMultiValueInputStream() throws RepositoryException {
        final Session s = slingRepository.loginAdministrative(null);
        try {
            final String path = getClass().getSimpleName() + System.currentTimeMillis();
            final Node child = s.getRootNode().addNode(path);
            final Property p = child.setProperty("foo", new String[] { "bar", "wii " });
            s.save();
            try {
                p.getBinary().getStream();
                fail("Expecting getStream() to fail on a multi-value Property");
            } catch(RepositoryException asExpected) {
            }
        } finally {
            s.logout();
        }
    }

    @Test
    @Ignore
    public void testResourceEvents() throws RepositoryException {
        final AddedResourceChangeListener listener = new AddedResourceChangeListener();
        final Dictionary<String, Object> properties = new Hashtable<>();
        properties.put(ResourceChangeListener.PATHS, "/");
        properties.put(ResourceChangeListener.CHANGES, "ADDED"); // ChangeType.ADDED
        final ServiceRegistration reg = bundleContext.registerService(ResourceChangeListener.class, listener, properties);
        final Session s = slingRepository.loginAdministrative(null);
        final int nPaths = 2500 * TEST_SCALE;
        final int timeoutMsec = 2 * nPaths;
        final String prefix = uniqueName("testResourceObservationEvents");

        // Create N nodes with a unique name under /
        // and verify that ResourceChangeListener gets notified
        // for each of them
        try {
            for(int i=0; i  < nPaths; i++) {
                s.getRootNode().addNode(prefix + i);
            }
            s.save();

            logger.info("Added {} nodes, checking what ResourceChangeListener got...", nPaths);
            final long timeout = System.currentTimeMillis() + timeoutMsec;
            final Set<String> missing = new HashSet<String>();
            while(System.currentTimeMillis() < timeout) {
                missing.clear();
                final Set<String> paths = listener.getPaths();
                for(int i=0; i  < nPaths; i++) {
                    final String path = "/" + prefix + i;
                    if(!paths.contains(path)) {
                        missing.add(path);
                    }
                }

                if(missing.isEmpty()) {
                    break;
                }
            }

            if(!missing.isEmpty()) {
                final String missingStr = missing.size() > 10 ? missing.size() + " paths missing" : missing.toString();
                fail("resource added events are missing for "
                    + missing.size() + "/" + nPaths + " paths after "
                    + timeoutMsec + " msec: " + missingStr);
            }
        } finally {
            reg.unregister();
            s.logout();
        }

        logger.info("Successfully detected resource observation events for " + nPaths + " paths");
    }

    @Test
    public void testNodetypeObservation() throws Exception {
        Session s = slingRepository.loginAdministrative(null);
        final Reader cnd = new StringReader(I18N_MESSAGE_CND);
        JcrEventsCounter counter = null;
        final String path = "/" + uniqueName("observation");

        // Add a sling:MessageEntry and verify that we get JCR events
        try {
            CndImporter.registerNodeTypes(cnd, s);
            counter = new JcrEventsCounter();

            final Node n = s.getRootNode().addNode(path.substring(1), "sling:MessageEntry");
            n.setProperty("sling:key", "foo");
            n.setProperty("sling:message", "bar");
            s.save();

            final JcrEventsCounter c = counter;
            new Retry(5000) {
                @Override
                protected void exec() throws Exception {
                    assertTrue("Expecting JCR events after adding " + path, c.get() > 0);
                }
            };

        } finally {
            s.logout();
            cnd.close();
            if(counter != null) {
                counter.close();
            }
        }

        // In a separate session, modify node and verify that we get events
        counter = new JcrEventsCounter();
        s = slingRepository.loginAdministrative(null);
        try {

            final Node n = s.getNode(path);
            n.setProperty("sling:message", "CHANGED now");
            s.save();

            final JcrEventsCounter c = counter;
            new Retry(5000) {
                @Override
                protected void exec() throws Exception {
                    assertTrue("Expecting JCR events after modifying " + path, c.get() > 0);
                }
            };

        } finally {
            s.logout();
            cnd.close();
            counter.close();
        }

    }

    public class AddedResourceChangeListener implements ResourceChangeListener {

        private Set<String> paths =  new LinkedHashSet<>();

        private final Object lock = new Object();

        private final Logger logger = LoggerFactory.getLogger(AddedResourceChangeListener.class);

        AddedResourceChangeListener() {
        }

        Set<String> getPaths() {
            synchronized (lock) {
                return Collections.unmodifiableSet(paths);
            }
        }

        @Override
        public void onChange(final List<ResourceChange> list) {
            synchronized (lock) {
                logger.info("{} resources added already", paths.size());
                logger.info("{} new resource changes", list.size());
                for (final ResourceChange resourceChange : list) {
                    if (resourceChange.getType() == ChangeType.ADDED) {
                        paths.add(resourceChange.getPath());
                    }
                }
                logger.info("{} resources added in total", paths.size());
            }
        }

    }

}
