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

import static org.hamcrest.Matchers.arrayWithSize;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.path.Path;
import org.apache.sling.api.resource.path.PathSet;
import org.apache.sling.api.resource.runtime.dto.AuthType;
import org.apache.sling.api.resource.runtime.dto.RuntimeDTO;
import org.apache.sling.resourceresolver.impl.Fixture;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker.ChangeListener;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker.ObservationReporterGenerator;
import org.apache.sling.spi.resource.provider.ObservationReporter;
import org.apache.sling.spi.resource.provider.ObserverConfiguration;
import org.apache.sling.spi.resource.provider.ResourceProvider;
import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.event.EventAdmin;

public class ResourceProviderTrackerTest {

    @Rule
    public OsgiContext context = new OsgiContext();

    private EventAdmin eventAdmin;
    private ResourceProviderInfo rp2Info;
    private Fixture fixture;

    @Before
    public void prepare() throws Exception {
        eventAdmin = context.getService(EventAdmin.class);
        fixture = new Fixture(context.bundleContext());
    }

    private ResourceProviderTracker registerDefaultResourceProviderTracker() throws Exception {
        @SuppressWarnings("unchecked")
        ResourceProvider<Object> rp = mock(ResourceProvider.class);
        @SuppressWarnings("unchecked")
        ResourceProvider<Object> rp2 = mock(ResourceProvider.class);
        @SuppressWarnings("unchecked")
        ResourceProvider<Object> rp3 = mock(ResourceProvider.class);

        fixture.registerResourceProvider(rp, "/", AuthType.no);
        rp2Info = fixture.registerResourceProvider(rp2, "/path", AuthType.lazy);
        fixture.registerResourceProvider(rp3, "invalid", AuthType.no);

        ResourceProviderTracker tracker = new ResourceProviderTracker();
        tracker.setObservationReporterGenerator(new SimpleObservationReporterGenerator(new DoNothingObservationReporter()));
        tracker.activate(context.bundleContext(), eventAdmin, new DoNothingChangeListener());
        return tracker;
    }

    @Test
    public void activate() throws Exception {
        ResourceProviderTracker tracker = registerDefaultResourceProviderTracker();

        // since the OSGi mocks are asynchronous we don't have to wait for the changes to propagate

        assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(2));

        fixture.unregisterResourceProvider(rp2Info);

        assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(1));
    }

    @Test
    public void deactivate() throws Exception {
        ResourceProviderTracker tracker = registerDefaultResourceProviderTracker();

        tracker.deactivate();

        assertThat(tracker.getResourceProviderStorage().getAllHandlers(), hasSize(0));
    }

    @Test
    public void testActivationDeactivation() throws Exception {
        final ResourceProviderTracker tracker = new ResourceProviderTracker();
        tracker.setObservationReporterGenerator(new SimpleObservationReporterGenerator(new DoNothingObservationReporter()));

        // create boolean markers for the listener
        final AtomicBoolean addedCalled = new AtomicBoolean(false);
        final AtomicBoolean removedCalled = new AtomicBoolean(false);

        final ChangeListener listener = new ChangeListener() {

            @Override
            public void providerAdded() {
                addedCalled.set(true);
            }

            @Override
            public void providerRemoved(String name, String pid, boolean stateful, boolean used) {
                removedCalled.set(true);
            }

        };
        // activate and check that no listener is called yet
        tracker.activate(context.bundleContext(), eventAdmin, listener);
        assertFalse(addedCalled.get());
        assertFalse(removedCalled.get());

        // add a new resource provider
        @SuppressWarnings("unchecked")
        ResourceProvider<Object> rp = mock(ResourceProvider.class);
        final ResourceProviderInfo info = fixture.registerResourceProvider(rp, "/", AuthType.no);

        // check added is called but not removed
        assertTrue(addedCalled.get());
        assertFalse(removedCalled.get());

        // verify a single provider
        assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(1));

        // reset boolean markers
        addedCalled.set(false);
        removedCalled.set(false);

        // remove provider
        fixture.unregisterResourceProvider(info);

        // verify removed is called but not added
        assertTrue(removedCalled.get());
        assertFalse(addedCalled.get());

        // no provider anymore
        assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(0));
    }

    @Test
    public void testReactivation() throws Exception {
        final ResourceProviderTracker tracker = new ResourceProviderTracker();
        tracker.setObservationReporterGenerator(new SimpleObservationReporterGenerator(new DoNothingObservationReporter()));

        // create boolean markers for the listener
        final AtomicBoolean addedCalled = new AtomicBoolean(false);
        final AtomicBoolean removedCalled = new AtomicBoolean(false);

        final ChangeListener listener = new ChangeListener() {

            @Override
            public void providerAdded() {
                addedCalled.set(true);
            }

            @Override
            public void providerRemoved(String name, String pid, boolean stateful, boolean used) {
                removedCalled.set(true);
            }

        };
        // activate and check that no listener is called yet
        tracker.activate(context.bundleContext(), eventAdmin, listener);
        assertFalse(addedCalled.get());
        assertFalse(removedCalled.get());

        // activate and check that no listener is called yet
        @SuppressWarnings("unchecked")
        ResourceProvider<Object> rp = mock(ResourceProvider.class);
        final ResourceProviderInfo info = fixture.registerResourceProvider(rp, "/", AuthType.no);

        // check added is called but not removed
        assertTrue(addedCalled.get());
        assertFalse(removedCalled.get());

        // verify a single provider
        assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(1));

        // reset boolean markers
        addedCalled.set(false);
        removedCalled.set(false);

        // add overlay provider with higher service ranking
        @SuppressWarnings("unchecked")
        ResourceProvider<Object> rp2 = mock(ResourceProvider.class);
        final ResourceProviderInfo infoOverlay = fixture.registerResourceProvider(rp2, "/", AuthType.no, 1000);

        // check added and removed is called
        assertTrue(addedCalled.get());
        assertTrue(removedCalled.get());

        // verify a single provider
        assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(1));

        // reset boolean markers
        addedCalled.set(false);
        removedCalled.set(false);

        // unregister overlay provider
        fixture.unregisterResourceProvider(infoOverlay);

        // check added and removed is called
        assertTrue(addedCalled.get());
        assertTrue(removedCalled.get());

        // verify a single provider
        assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(1));

        // reset boolean markers
        addedCalled.set(false);
        removedCalled.set(false);

        // unregister first provider
        fixture.unregisterResourceProvider(info);

        // check removed is called but not added
        assertTrue(removedCalled.get());
        assertFalse(addedCalled.get());

        // verify no provider
        assertThat(tracker.getResourceProviderStorage().getAllHandlers().size(), equalTo(0));
    }

    /**
     * This test verifies that shadowing of Resource observation is deterministic when ResourceProviders get registered and unregistered,
     * meaning it is independent of the order in which those events happen.
     * <p>
     * It does so by
     * 1) registering a ResourceProvider A on a deeper path then root (shadowing root)
     * 2) registering a ResourceProvider B on root
     * 3) unregistering the ResourceProvider A
     * 4) and registering the ResoucreProvider A
     * <p>
     * This guarantees in both cases (A before B and B before A) the same excludes are applied in the ObservationReporter.
     *
     * @throws InvalidSyntaxException
     */
    @Test
    public void testDeterministicObservationShadowing() throws InvalidSyntaxException {
        final ResourceProviderTracker tracker = new ResourceProviderTracker();
        final Map<String, List<String>> excludeSets = new HashMap<>();

        tracker.activate(context.bundleContext(), eventAdmin, null);
        tracker.setObservationReporterGenerator(new SimpleObservationReporterGenerator(new DoNothingObservationReporter()) {
            @Override
            public ObservationReporter create(Path path, PathSet excludes) {
                List<String> excludeSetsPerPath = excludeSets.get(path.getPath());
                if (excludeSetsPerPath == null) {
                    excludeSetsPerPath = new ArrayList<>(1);
                    excludeSets.put(path.getPath(), excludeSetsPerPath);
                }

                excludeSetsPerPath.clear();
                for (Path exclude : excludes) {
                    excludeSetsPerPath.add(exclude.getPath());
                }

                return super.create(path, excludes);
            }
        });

        ResourceProvider<?> rp = mock(ResourceProvider.class);
        ResourceProviderInfo info;
        // register RP on /path, empty exclude set expected
        info = fixture.registerResourceProvider(rp, "/path", AuthType.no);
        assertNull(excludeSets.get("/"));
        // register RP on /, expect /path excluded
        fixture.registerResourceProvider(rp, "/", AuthType.no);
        assertThat(excludeSets.get("/"), hasSize(1));
        assertThat(excludeSets.get("/"), contains("/path"));
        // unregister RP on /path,  empty exclude set expected
        fixture.unregisterResourceProvider(info);
        assertThat(excludeSets.get("/"), hasSize(0));
        // register RP on /path again, expect /path excluded
        fixture.registerResourceProvider(rp, "/path", AuthType.no);
        assertThat(excludeSets.get("/"), hasSize(1));
        assertThat(excludeSets.get("/"), contains("/path"));
    }

    @Test
    public void fillDto() throws Exception {
        ResourceProviderTracker tracker = registerDefaultResourceProviderTracker();

        RuntimeDTO dto = new RuntimeDTO();

        tracker.fill(dto);

        assertThat( dto.providers, arrayWithSize(2));
        assertThat( dto.failedProviders, arrayWithSize(1));
    }

    static class DoNothingObservationReporter implements ObservationReporter {
        @Override
        public void reportChanges(Iterable<ResourceChange> changes, boolean distribute) {
        }

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

        @Override
        public List<ObserverConfiguration> getObserverConfigurations() {
            return Collections.emptyList();
        }
    }

    static class SimpleObservationReporterGenerator implements ObservationReporterGenerator {
        private final ObservationReporter reporter;

        SimpleObservationReporterGenerator(ObservationReporter reporter) {
            this.reporter = reporter;
        }

        @Override
        public ObservationReporter createProviderReporter() {
            return reporter;
        }

        @Override
        public ObservationReporter create(Path path, PathSet excludes) {
            return reporter;
        }
    }

    static final class DoNothingChangeListener implements ChangeListener {

        @Override
        public void providerAdded() {
            // TODO Auto-generated method stub

        }

        @Override
        public void providerRemoved(String name, String pid, boolean stateful, boolean used) {
            // TODO Auto-generated method stub

        }
    }
}