/*
 * 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.junit.Assert.*;
import static org.mockito.Mockito.*;

import java.util.ArrayList;
import java.util.Arrays;
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.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;
    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(componentContext.getBundleContext()).thenReturn(bundleContext);
        when(componentContext.getProperties()).thenReturn(componentContextProperties);
        when(componentContextProperties.get(SuperimposingManagerImpl.OBSERVATION_PATHS_PROPERTY)).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 {
        when(componentContextProperties.get(SuperimposingManagerImpl.ENABLED_PROPERTY)).thenReturn(enabled);

        underTest = new SuperimposingManagerImpl().withResourceResolverFactory(resourceResolverFactory);
        underTest.activate(componentContext);

        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(componentContextProperties.get(SuperimposingManagerImpl.FINDALLQUERIES_PROPERTY)).thenReturn("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);

        // 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(componentContextProperties.get(SuperimposingManagerImpl.FINDALLQUERIES_PROPERTY)).thenReturn("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));
    }

}
