/*
 * 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.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 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, 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 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<>();
                }
            };
            return Collections.singletonList(config);
        }

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

}
