/*
 * 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.superimposing.impl;

import static org.apache.sling.superimposing.SuperimposingResourceProvider.PROP_SUPERIMPOSE_OVERLAYABLE;
import static org.apache.sling.superimposing.SuperimposingResourceProvider.PROP_SUPERIMPOSE_REGISTER_PARENT;
import static org.apache.sling.superimposing.SuperimposingResourceProvider.PROP_SUPERIMPOSE_SOURCE_PATH;
import static org.apache.sling.superimposing.impl.SuperimposingManagerImpl.FIND_ALL_QUERIES_DEFAULT;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;

import org.apache.commons.collections.IteratorUtils;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.apache.sling.superimposing.SuperimposingResourceProvider;
import org.apache.sling.superimposing.impl.SuperimposingManagerImpl.SuperimposingManagerConfig;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;

@RunWith(MockitoJUnitRunner.class)
public class SuperimposingManagerImplTest {

    @Mock
    private Dictionary<String, Object> componentContextProperties;
    @Mock
    private ComponentContext componentContext;
    @Mock
    private BundleContext bundleContext;
    @Mock
    private ResourceResolverFactory resourceResolverFactory;
    @Mock
    private ResourceResolver resourceResolver;
    @Mock(answer=Answers.RETURNS_DEEP_STUBS)
    private Session session;
    @Mock
    private SuperimposingManagerConfig configuration;

    private List<ServiceRegistration> serviceRegistrations = new ArrayList<ServiceRegistration>();

    private SuperimposingManagerImpl underTest;

    private static final String ORIGINAL_PATH = "/root/path1";
    private static final String SUPERIMPOSED_PATH = "/root/path2";
    private static final String OBSERVATION_PATH = "/root";

    @SuppressWarnings("unchecked")
    @Before
    public void setUp() throws LoginException {
        when(configuration.enabled()).thenReturn(true);
        when(configuration.findAllQueries()).thenReturn(new String[] {FIND_ALL_QUERIES_DEFAULT});
        when(configuration.observationPaths()).thenReturn(new String[] {OBSERVATION_PATH});
        when(resourceResolverFactory.getAdministrativeResourceResolver(any(Map.class))).thenReturn(resourceResolver);
        when(resourceResolver.adaptTo(Session.class)).thenReturn(session);

        // collect a list of all service registrations to validate that they are all unregistered on shutdown
        when(bundleContext.registerService(anyString(), anyObject(), any(Dictionary.class))).thenAnswer(new Answer<ServiceRegistration>() {
            public ServiceRegistration answer(InvocationOnMock invocation) {
                final ServiceRegistration mockRegistration = mock(ServiceRegistration.class);
                serviceRegistrations.add(mockRegistration);
                doAnswer(new Answer() {
                    public Object answer(InvocationOnMock invocation) {
                        return serviceRegistrations.remove(mockRegistration);
                    }
                }).when(mockRegistration).unregister();
                return mockRegistration;
            }
        });

        // simulate absolute path access to properties via session object
        try {
            when(session.itemExists(anyString())).thenAnswer(new Answer<Boolean>() {
                public Boolean answer(InvocationOnMock invocation) throws Throwable {
                    final String absolutePath = (String)invocation.getArguments()[0];
                    final String nodePath = ResourceUtil.getParent(absolutePath);
                    final String propertyName = ResourceUtil.getName(absolutePath);
                    Resource resource = resourceResolver.getResource(nodePath);
                    if (resource!=null) {
                        ValueMap props = resource.adaptTo(ValueMap.class);
                        return props.containsKey(propertyName);
                    }
                    else {
                        return false;
                    }
                }
            });
            when(session.getProperty(anyString())).thenAnswer(new Answer<Property>() {
                public Property answer(InvocationOnMock invocation) throws Throwable {
                    final String absolutePath = (String)invocation.getArguments()[0];
                    final String nodePath = ResourceUtil.getParent(absolutePath);
                    final String propertyName = ResourceUtil.getName(absolutePath);
                    Resource resource = resourceResolver.getResource(nodePath);
                    if (resource!=null) {
                        ValueMap props = resource.adaptTo(ValueMap.class);
                        Object value = props.get(propertyName);
                        if (value==null) {
                            throw new PathNotFoundException();
                        }
                        Property prop = mock(Property.class);
                        when(prop.getName()).thenReturn(propertyName);
                        if (value instanceof String) {
                            when(prop.getString()).thenReturn((String)value);
                        }
                        else if (value instanceof Boolean) {
                            when(prop.getBoolean()).thenReturn((Boolean)value);
                        }
                        return prop;
                    }
                    else {
                        throw new PathNotFoundException();
                    }
                }
            });
        }
        catch (RepositoryException ex) {
            throw new RuntimeException(ex);
        }
    }

    private void initialize(boolean enabled) throws InterruptedException, LoginException, RepositoryException {
        this.initialize(enabled, true);
    }

    private void initialize(boolean enabled, boolean createDefaultFind) throws InterruptedException, LoginException, RepositoryException {
        when(configuration.enabled()).thenReturn(enabled);
        if(createDefaultFind) {
            when(resourceResolver.findResources(anyString(), anyString())).thenReturn(Collections.emptyIterator());
        }

        underTest = new SuperimposingManagerImpl().withResourceResolverFactory(resourceResolverFactory);
        underTest.activate(bundleContext, configuration);

        if (underTest.isEnabled()) {
            // verify observation registration
            verify(session.getWorkspace().getObservationManager()).addEventListener(any(EventListener.class), anyInt(), eq(OBSERVATION_PATH), anyBoolean(), any(String[].class), any(String[].class), anyBoolean());
            // wait until separate initialization thread has finished
            while (!underTest.initialization.isDone()) {
                Thread.sleep(10);
            }
        }
    }

    @After
    public void tearDown() throws RepositoryException {
        underTest.deactivate(componentContext);

        if (underTest.isEnabled()) {
            // verify observation and resource resolver are terminated correctly
            verify(session.getWorkspace().getObservationManager()).removeEventListener(any(EventListener.class));
            verify(resourceResolver).close();
        }

        // make sure all registrations are unregistered on shutdown
        for (ServiceRegistration registration : serviceRegistrations) {
            verify(registration, times(1)).unregister();
        }
    }

    private Resource prepareSuperimposingResource(String superimposedPath, String sourcePath, boolean registerParent, boolean overlayable) {
        Resource resource = mock(Resource.class);
        when(resource.getPath()).thenReturn(superimposedPath);
        ValueMap props = new ValueMapDecorator(new HashMap<String, Object>());
        props.put(PROP_SUPERIMPOSE_SOURCE_PATH, sourcePath);
        props.put(PROP_SUPERIMPOSE_REGISTER_PARENT, registerParent);
        props.put(PROP_SUPERIMPOSE_OVERLAYABLE, overlayable);
        when(resource.adaptTo(ValueMap.class)).thenReturn(props);
        when(resourceResolver.getResource(superimposedPath)).thenReturn(resource);
        return resource;
    }

    private void moveSuperimposedResource(Resource resource, String newPath) {
        String oldPath = resource.getPath();
        when(resource.getPath()).thenReturn(newPath);
        when(resourceResolver.getResource(oldPath)).thenReturn(null);
        when(resourceResolver.getResource(newPath)).thenReturn(resource);
    }

    @Test
    public void testDisabled() throws InterruptedException, LoginException, RepositoryException {
        // make sure that no exception is thrown when service is disabled on activate/deactivate
        initialize(false);

        verifyZeroInteractions(resourceResolverFactory);
        verifyZeroInteractions(bundleContext);
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testFindAllSuperimposings() throws InterruptedException, LoginException, RepositoryException {
        // prepare a query that returns one existing superimposed resource
        when(configuration.findAllQueries()).thenReturn(new String[] {"syntax|query"});
        when(resourceResolver.findResources("query", "syntax")).then(new Answer<Iterator<Resource>>() {
            public Iterator<Resource> answer(InvocationOnMock invocation) {
                return Arrays.asList(new Resource[] {
                        prepareSuperimposingResource(SUPERIMPOSED_PATH, ORIGINAL_PATH, false, false)
                }).iterator();
            }
        });
        initialize(true, false);

        // ensure the superimposed resource is detected and registered
        List<SuperimposingResourceProvider> providers = IteratorUtils.toList(underTest.getRegisteredProviders());
        assertEquals(1, providers.size());
        SuperimposingResourceProvider provider = providers.iterator().next();
        assertEquals(SUPERIMPOSED_PATH, provider.getRootPath());
        assertEquals(ORIGINAL_PATH, provider.getSourcePath());
        assertFalse(provider.isOverlayable());
        verify(bundleContext).registerService(anyString(), same(provider), any(Dictionary.class));
    }

    private EventIterator prepareNodeCreateEvent(Resource pResource) throws RepositoryException {
        String resourcePath = pResource.getPath();

        Event nodeEvent = mock(Event.class);
        when(nodeEvent.getType()).thenReturn(Event.NODE_ADDED);
        when(nodeEvent.getPath()).thenReturn(resourcePath);

        Event propertyEvent = mock(Event.class);
        when(propertyEvent.getType()).thenReturn(Event.PROPERTY_ADDED);
        when(propertyEvent.getPath()).thenReturn(resourcePath + "/" + SuperimposingResourceProvider.PROP_SUPERIMPOSE_SOURCE_PATH);

        EventIterator eventIterator = mock(EventIterator.class);
        when(eventIterator.hasNext()).thenReturn(true, true, false);
        when(eventIterator.nextEvent()).thenReturn(nodeEvent, propertyEvent);
        return eventIterator;
    }

    private EventIterator prepareNodeChangeEvent(Resource pResource) throws RepositoryException {
        String resourcePath = pResource.getPath();

        Event propertyEvent = mock(Event.class);
        when(propertyEvent.getType()).thenReturn(Event.PROPERTY_CHANGED);
        when(propertyEvent.getPath()).thenReturn(resourcePath + "/" + SuperimposingResourceProvider.PROP_SUPERIMPOSE_SOURCE_PATH);

        EventIterator eventIterator = mock(EventIterator.class);
        when(eventIterator.hasNext()).thenReturn(true, false);
        when(eventIterator.nextEvent()).thenReturn(propertyEvent);
        return eventIterator;
    }

    private EventIterator prepareNodeRemoveEvent(Resource pResource) throws RepositoryException {
        String resourcePath = pResource.getPath();

        Event nodeEvent = mock(Event.class);
        when(nodeEvent.getType()).thenReturn(Event.NODE_REMOVED);
        when(nodeEvent.getPath()).thenReturn(resourcePath);

        EventIterator eventIterator = mock(EventIterator.class);
        when(eventIterator.hasNext()).thenReturn(true, false);
        when(eventIterator.nextEvent()).thenReturn(nodeEvent);
        return eventIterator;
    }

    private EventIterator prepareNodeMoveEvent(Resource pResource, String pOldPath) throws RepositoryException {
        String resourcePath = pResource.getPath();

        Event nodeRemoveEvent = mock(Event.class);
        when(nodeRemoveEvent.getType()).thenReturn(Event.NODE_REMOVED);
        when(nodeRemoveEvent.getPath()).thenReturn(pOldPath);

        Event nodeCreateEvent = mock(Event.class);
        when(nodeCreateEvent.getType()).thenReturn(Event.NODE_ADDED);
        when(nodeCreateEvent.getPath()).thenReturn(resourcePath);

        EventIterator eventIterator = mock(EventIterator.class);
        when(eventIterator.hasNext()).thenReturn(true, true, false);
        when(eventIterator.nextEvent()).thenReturn(nodeRemoveEvent, nodeCreateEvent);
        return eventIterator;
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testSuperimposedResourceCreateUpdateRemove() throws InterruptedException, LoginException, RepositoryException {
        initialize(true);

        // simulate node create event
        Resource superimposedResource = prepareSuperimposingResource(SUPERIMPOSED_PATH, ORIGINAL_PATH, false, false);
        underTest.onEvent(prepareNodeCreateEvent(superimposedResource));

        // ensure the superimposed resource is detected and registered
        List<SuperimposingResourceProvider> providers = IteratorUtils.toList(underTest.getRegisteredProviders());
        assertEquals(1, providers.size());
        SuperimposingResourceProvider provider = providers.iterator().next();
        assertEquals(SUPERIMPOSED_PATH, provider.getRootPath());
        assertEquals(ORIGINAL_PATH, provider.getSourcePath());
        assertFalse(provider.isOverlayable());
        verify(bundleContext).registerService(anyString(), same(provider), any(Dictionary.class));

        // simulate a change in the original path
        superimposedResource.adaptTo(ValueMap.class).put(PROP_SUPERIMPOSE_SOURCE_PATH, "/other/path");
        underTest.onEvent(prepareNodeChangeEvent(superimposedResource));

        // ensure the superimposed resource update is detected and a new provider instance is registered
        providers = IteratorUtils.toList(underTest.getRegisteredProviders());
        assertEquals(1, providers.size());
        SuperimposingResourceProvider provider2 = providers.iterator().next();
        assertEquals(SUPERIMPOSED_PATH, provider2.getRootPath());
        assertEquals("/other/path", provider2.getSourcePath());
        assertFalse(provider2.isOverlayable());
        verify(bundleContext).registerService(anyString(), same(provider2), any(Dictionary.class));

        // simulate node removal
        underTest.onEvent(prepareNodeRemoveEvent(superimposedResource));

        // ensure provider is removed
        providers = IteratorUtils.toList(underTest.getRegisteredProviders());
        assertEquals(0, providers.size());
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testSuperimposedResourceCreateMove() throws InterruptedException, LoginException, RepositoryException {
        when(configuration.findAllQueries()).thenReturn(new String[] {"syntax|query"});
        initialize(true);

        // simulate node create event
        final Resource superimposedResource = prepareSuperimposingResource(SUPERIMPOSED_PATH, ORIGINAL_PATH, false, false);
        underTest.onEvent(prepareNodeCreateEvent(superimposedResource));

        // simulate a node move event
        String oldPath = superimposedResource.getPath();
        moveSuperimposedResource(superimposedResource, "/new/path");

        // prepare a query that returns the moved superimposed resource
        when(resourceResolver.findResources("query", "syntax")).then(new Answer<Iterator<Resource>>() {
            public Iterator<Resource> answer(InvocationOnMock invocation) {
                return Arrays.asList(new Resource[] {
                        superimposedResource
                }).iterator();
            }
        });

        underTest.onEvent(prepareNodeMoveEvent(superimposedResource, oldPath));

        // ensure the superimposed resource update is detected and a new provider instance is registered
        List<SuperimposingResourceProvider> providers = IteratorUtils.toList(underTest.getRegisteredProviders());
        assertEquals(1, providers.size());
        SuperimposingResourceProvider provider = providers.iterator().next();
        assertEquals("/new/path", provider.getRootPath());
        assertEquals(ORIGINAL_PATH, provider.getSourcePath());
        assertFalse(provider.isOverlayable());
        verify(bundleContext).registerService(anyString(), same(provider), any(Dictionary.class));
    }

}
