/*
 * 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.jcr.resource.internal;

import static java.util.Collections.synchronizedList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.jcr.Credentials;
import javax.jcr.LoginException;
import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;

import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
import org.apache.sling.api.resource.path.PathSet;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.resource.internal.helper.jcr.SlingRepositoryProvider;
import org.apache.sling.spi.resource.provider.ObservationReporter;
import org.apache.sling.spi.resource.provider.ObserverConfiguration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * Test of JcrResourceListener.
 */
public class JcrResourceListenerTest {

    private JcrListenerBaseConfig config;

    private JcrResourceListener listener;

    private Session adminSession;

    private String createdPath = "/test" + System.currentTimeMillis() + "-create";

    private String pathToDelete = "/test" + System.currentTimeMillis() + "-delete";

    private String pathToModify = "/test" + System.currentTimeMillis() + "-modify";

    private final List<ResourceChange> events = synchronizedList(new ArrayList<ResourceChange>());

    SlingRepository repository;

    @SuppressWarnings("deprecation")
    @Before
    public void setUp() throws Exception {
        repository = SlingRepositoryProvider.getRepository();
        this.adminSession = repository.loginAdministrative(null);
        ObservationReporter observationReporter = getObservationReporter();
        this.config = new JcrListenerBaseConfig(observationReporter,
                new SlingRepository() {

                    @Override
                    public Session login(Credentials credentials, String workspaceName)
                            throws LoginException, NoSuchWorkspaceException, RepositoryException {
                        return repository.login(credentials, workspaceName);
                    }

                    @Override
                    public Session login(String workspaceName) throws LoginException, NoSuchWorkspaceException, RepositoryException {
                        return repository.login(workspaceName);
                    }

                    @Override
                    public Session login(Credentials credentials) throws LoginException, RepositoryException {
                        return repository.login(credentials);
                    }

                    @Override
                    public Session login() throws LoginException, RepositoryException {
                        return repository.login();
                    }

                    @Override
                    public boolean isStandardDescriptor(String key) {
                        return repository.isStandardDescriptor(key);
                    }

                    @Override
                    public boolean isSingleValueDescriptor(String key) {
                        return repository.isSingleValueDescriptor(key);
                    }

                    @Override
                    public Value[] getDescriptorValues(String key) {
                        return repository.getDescriptorValues(key);
                    }

                    @Override
                    public Value getDescriptorValue(String key) {
                        return repository.getDescriptorValue(key);
                    }

                    @Override
                    public String[] getDescriptorKeys() {
                        return repository.getDescriptorKeys();
                    }

                    @Override
                    public String getDescriptor(String key) {
                        return repository.getDescriptor(key);
                    }

                    @Override
                    public Session loginService(String subServiceName, String workspace) throws LoginException, RepositoryException {
                        return repository.loginAdministrative(workspace);
                    }

                    @Override
                    public Session loginAdministrative(String workspace) throws LoginException, RepositoryException {
                        return repository.loginAdministrative(workspace);
                    }

                    @Override
                    public String getDefaultWorkspace() {
                        // TODO Auto-generated method stub
                        return repository.getDefaultWorkspace();
                    }
                });
        this.listener = new JcrResourceListener(this.config,
                observationReporter.getObserverConfigurations().get(0));
    }

    @After
    public void tearDown() throws Exception {
        if ( adminSession != null ) {
            adminSession.logout();
            adminSession = null;
        }
        if ( listener != null ) {
            listener.close();
            listener = null;
        }
        if ( config != null ) {
            config.close();
            config = null;
        }
    }

    @Test
    public void testSimpleOperations() throws Exception {
        generateEvents(adminSession);
        assertEquals("Received: " + events, 5, events.size());
        final Set<String> addPaths = new HashSet<String>();
        final Set<String> modifyPaths = new HashSet<String>();
        final Set<String> removePaths = new HashSet<String>();

        for (final ResourceChange event : events) {
            if (event.getType() == ChangeType.ADDED) {
                addPaths.add(event.getPath());
            } else if (event.getType() == ChangeType.CHANGED) {
                modifyPaths.add(event.getPath());
            } else if (event.getType() == ChangeType.REMOVED) {
                removePaths.add(event.getPath());
            } else {
                fail("Unexpected event: " + event);
            }
            assertNotNull(event.getUserId());
        }

        assertEquals(3, addPaths.size());
        assertTrue("Added set should contain " + createdPath, addPaths.contains(createdPath));
        assertTrue("Added set should contain " + pathToDelete, addPaths.contains(pathToDelete));
        assertTrue("Added set should contain " + pathToModify, addPaths.contains(pathToModify));

        assertEquals(1, modifyPaths.size());
        assertTrue("Modified set should contain " + pathToModify, modifyPaths.contains(pathToModify));

        assertEquals(1, removePaths.size());
        assertTrue("Removed set should contain " + pathToDelete, removePaths.contains(pathToDelete));
    }

    @Test
    public void testMultiplePaths() throws Exception {
        ObserverConfiguration observerConfig = new ObserverConfiguration() {

            @Override
            public boolean includeExternal() {
                return true;
            }

            @Override
            public PathSet getPaths() {
                return PathSet.fromStrings("/libs", "/apps");
            }

            @Override
            public PathSet getExcludedPaths() {
                return PathSet.fromPaths();
            }

            @Override
            public Set<ChangeType> getChangeTypes() {
                return EnumSet.allOf(ChangeType.class);
            }

            @Override
            public boolean matches(String path) {
                return this.getPaths().matches(path) != null;
            }

            @Override
            public Set<String> getPropertyNamesHint() {
                return null;
            }
        };
        this.config.unregister(this.listener);
        this.listener = null;
        final Session session = this.adminSession;
        if ( !session.nodeExists("/libs") ) {
            createNode(session, "/libs");
        }
        if ( !session.nodeExists("/apps") ) {
            createNode(session, "/apps");
        }
        session.getNode("/libs").addNode("foo" + System.currentTimeMillis());
        session.getNode("/apps").addNode("foo" + System.currentTimeMillis());

        session.save();

        Thread.sleep(200);

        this.events.clear();

        try ( final JcrResourceListener l = new JcrResourceListener(this.config, observerConfig)) {
            final String rootName = "test_" + System.currentTimeMillis();
            for ( final String path : new String[] {"/libs", "/", "/apps", "/content"}) {
                final Node parent;
                if ( !session.nodeExists(path) ) {
                    parent = createNode(session, path);
                } else {
                    parent = session.getNode(path);
                }
                final Node node = parent.addNode(rootName, "nt:unstructured");
                session.save();

                node.setProperty("foo", "bar");
                session.save();

                node.remove();
                session.save();
            }
            System.out.println("Events = " + events);
            assertEquals("Received: " + events, 7, events.size());
            final Set<String> addPaths = new HashSet<String>();
            final Set<String> modifyPaths = new HashSet<String>();
            final Set<String> removePaths = new HashSet<String>();

            for (final ResourceChange event : events) {
                if (event.getType() == ChangeType.ADDED) {
                    addPaths.add(event.getPath());
                } else if (event.getType() == ChangeType.CHANGED) {
                    modifyPaths.add(event.getPath());
                } else if (event.getType() == ChangeType.REMOVED) {
                    removePaths.add(event.getPath());
                } else {
                    fail("Unexpected event: " + event);
                }
                assertNotNull(event.getUserId());
            }
            assertEquals("Received: " + addPaths, 2, addPaths.size());
            assertTrue("Added set should contain /libs/" + rootName, addPaths.contains("/libs/" + rootName));
            assertTrue("Added set should contain /apps/" + rootName, addPaths.contains("/apps/" + rootName));

            assertEquals("Received: " + modifyPaths, 2, modifyPaths.size());
            assertTrue("Modified set should contain /libs/" + rootName, modifyPaths.contains("/libs/" + rootName));
            assertTrue("Modified set should contain /apps/" + rootName, modifyPaths.contains("/apps/" + rootName));

            // The OakEventFilter is using withIncludeAncestorsRemove, so we get also "removed" 
            // events for all ancestors of /apps and /libs;
            assertEquals("Received: " + removePaths, 3, removePaths.size());
            assertTrue("Removed set should contain /libs/" + rootName, removePaths.contains("/libs/" + rootName));
            assertTrue("Removed set should contain /apps/" + rootName, removePaths.contains("/apps/" + rootName));
            assertTrue("Removed set should contain /" + rootName, removePaths.contains("/" + rootName));
        }
    }

    private static Node createNode(final Session session, final String path) throws RepositoryException {
        final Node n = session.getRootNode().addNode(path.substring(1), "nt:unstructured");
        session.save();
        return n;
    }

    private void generateEvents(Session session) throws Exception {
        // create the nodes
        createNode(session, createdPath);
        createNode(session, pathToModify);
        createNode(session, pathToDelete);

        Thread.sleep(1000);

        // modify
        final Node modified = session.getNode(pathToModify);
        modified.setProperty("foo", "bar");

        session.save();

        // delete
        final Node deleted = session.getNode(pathToDelete);
        deleted.remove();
        session.save();

        Thread.sleep(3500);
    }

    protected ObservationReporter getObservationReporter() {
        return new SimpleObservationReporter();
    }

    private class SimpleObservationReporter implements ObservationReporter {

        @Override
        public void reportChanges(Iterable<ResourceChange> changes, boolean distribute) {
            for (ResourceChange c : changes) {
                events.add(c);
            }
        }

        @Override
        public List<ObserverConfiguration> getObserverConfigurations() {
            ObserverConfiguration config = new ObserverConfiguration() {

                @Override
                public boolean includeExternal() {
                    return true;
                }

                @Override
                public PathSet getPaths() {
                    return PathSet.fromStrings("/");
                }

                @Override
                public PathSet getExcludedPaths() {
                    return PathSet.fromPaths();
                }

                @Override
                public Set<ChangeType> getChangeTypes() {
                    return EnumSet.allOf(ChangeType.class);
                }

                @Override
                public boolean matches(String path) {
                    return true;
                }

                @Override
                public Set<String> getPropertyNamesHint() {
                    return new HashSet<String>();
                }
            };
            return Collections.singletonList(config);
        }

        @Override
        public void reportChanges(ObserverConfiguration config, Iterable<ResourceChange> changes, boolean distribute) {
            this.reportChanges(changes, distribute);
        }
    }

}
