/*
 * 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.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.jetbrains.annotations.NotNull;
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 final String createdPath = "/test" + System.currentTimeMillis() + "-create";

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

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

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

    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 RepositoryException {
                        return repository.login(credentials, workspaceName);
                    }

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

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

                    @Override
                    public Session login() throws 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 RepositoryException {
                        return repository.loginAdministrative(workspace);
                    }

                    @Override
                    public Session loginAdministrative(String workspace) throws 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() {
        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<>();
        final Set<String> modifyPaths = new HashSet<>();
        final Set<String> removePaths = new HashSet<>();

        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 Collections.emptySet();
            }
        };
        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, 6, events.size());
            final Set<String> addPaths = new HashSet<>();
            final Set<String> modifyPaths = new HashSet<>();
            final Set<String> removePaths = new HashSet<>();

            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));

            assertEquals("Received: " + removePaths, 2, removePaths.size());
            assertTrue("Removed set should contain /libs/" + rootName, removePaths.contains("/libs/" + rootName));
            assertTrue("Removed set should contain /apps/" + rootName, removePaths.contains("/apps/" + 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 @NotNull 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 Collections.emptySet();
                }
            };
            return Collections.singletonList(config);
        }

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

}
