/*
 * 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.helper.jcr;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeThat;
import static org.junit.Assume.assumeTrue;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jcr.Credentials;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;

import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.resource.api.JcrResourceConstants;
import org.apache.sling.spi.resource.provider.ResolveContext;
import org.apache.sling.spi.resource.provider.ResourceProvider;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;

@RunWith(Parameterized.class)
public class JcrResourceProviderSessionHandlingTest {

    private enum LoginStyle {USER, SESSION, SERVICE}

    private static final String AUTH_USER = UserConstants.DEFAULT_ADMIN_ID;
    private static final char[] AUTH_PASSWORD = AUTH_USER.toCharArray();
    private static final String SUDO_USER = UserConstants.DEFAULT_ANONYMOUS_ID;

    @Parameters(name = "loginStyle= {0}, sudo = {1}, clone = {2}")
    public static List<Object[]> data() {

        LoginStyle[] loginStyles = LoginStyle.values();
        boolean[] sudoOptions = new boolean[] {false, true};
        boolean[] cloneOptions = new boolean[] {false, true};

        // Generate all possible combinations into data.
        List<Object[]> data = new ArrayList<>();
        Object[] dataPoint = new Object[3];
        for (LoginStyle loginStyle : loginStyles) {
            dataPoint[0] = loginStyle;
            for (boolean sudo : sudoOptions) {
                dataPoint[1] = sudo;
                for (boolean clone : cloneOptions) {
                    dataPoint[2] = clone;
                    data.add(dataPoint.clone());
                }
            }
        }
        return data;
    }

    @Parameter(0)
    public LoginStyle loginStyle;

    @Parameter(1)
    public boolean useSudo;

    @Parameter(2)
    public boolean doClone;

    // Session we're using when loginStyle == SESSION, null otherwise.
    private Session explicitSession;
    // TransientRepository has a bug that makes it ignore sessions created
    // by calling Session.impersonate(). To prevent the repo from closing
    // prematurely, have this dummy session open during the whole lifetime
    // of the test.
    private Session footInDoor;

    private JcrResourceProvider jcrResourceProvider;
    private JcrProviderState jcrProviderState;

    private static class SlingRepositoryWithDummyServiceUsers implements SlingRepository {
        private final SlingRepository wrapped;
        
        SlingRepositoryWithDummyServiceUsers(SlingRepository wrapped) {
            this.wrapped = wrapped;
        }
        
        @SuppressWarnings("deprecation")
        @Override
        public Session loginService(String subServiceName, String workspace) throws RepositoryException {
            // just fake service logins by doing administrative logins instead
            return wrapped.loginAdministrative(workspace);
        }

        // the rest of the methods just delegate to wrapped

        @Override
        public String[] getDescriptorKeys() {
            return wrapped.getDescriptorKeys();
        }

        @Override
        public boolean isStandardDescriptor(String key) {
            return wrapped.isStandardDescriptor(key);
        }

        @Override
        public boolean isSingleValueDescriptor(String key) {
            return wrapped.isSingleValueDescriptor(key);
        }

        @Override
        public Value getDescriptorValue(String key) {
            return wrapped.getDescriptorValue(key);
        }

        @Override
        public Value[] getDescriptorValues(String key) {
            return wrapped.getDescriptorValues(key);
        }

        @Override
        public String getDescriptor(String key) {
            return wrapped.getDescriptor(key);
        }

        @Override
        public Session login(Credentials credentials, String workspaceName) throws RepositoryException {
            return wrapped.login(credentials, workspaceName);
        }

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

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

        @Override
        public Session login() throws RepositoryException {
            return wrapped.login();
        }

        @Override
        public String getDefaultWorkspace() {
            return wrapped.getDefaultWorkspace();
        }

        @SuppressWarnings("deprecation")
        @Override
        public Session loginAdministrative(String workspace) throws RepositoryException {
            return wrapped.loginAdministrative(workspace);
        }
        
    }

    @Before
    public void setUp() throws Exception {
        final SlingRepository repo = new SlingRepositoryWithDummyServiceUsers(SlingRepositoryProvider.getRepository());

        footInDoor = repo.loginAdministrative(null);

        Map<String, Object> authInfo = new HashMap<>();
        switch (loginStyle) {
        case USER:
            authInfo.put(ResourceResolverFactory.USER, AUTH_USER);
            authInfo.put(ResourceResolverFactory.PASSWORD, AUTH_PASSWORD);
            break;
        case SESSION:
            explicitSession = repo.loginAdministrative(null);
            authInfo.put(JcrResourceConstants.AUTHENTICATION_INFO_SESSION, explicitSession);
            break;
        case SERVICE:
            Bundle mockBundle = mock(Bundle.class);
            BundleContext mockBundleContext = mock(BundleContext.class);
            when(mockBundle.getBundleContext()).thenReturn(mockBundleContext);
            when(mockBundleContext.getService(Matchers.any())).thenReturn(repo);
            authInfo.put(ResourceResolverFactory.SUBSERVICE, "dummy-service");
            authInfo.put(ResourceProvider.AUTH_SERVICE_BUNDLE, mockBundle);
            break;
        }

        if (useSudo) {
            authInfo.put(ResourceResolverFactory.USER_IMPERSONATION, SUDO_USER);
        }

        if (doClone) {
            authInfo.put(ResourceProvider.AUTH_CLONE, true);
        }

        ComponentContext ctx = mock(ComponentContext.class);
        when(ctx.locateService(anyString(), Mockito.any())).thenReturn(repo);

        jcrResourceProvider = new JcrResourceProvider();
        jcrResourceProvider.activate(ctx);

        jcrProviderState = jcrResourceProvider.authenticate(authInfo);
    }

    @After
    public void tearDown() {

        // Some tests do a logout, so check for aliveness before trying to log out.
        if (jcrProviderState.getSession().isLive()) {
            jcrResourceProvider.logout(jcrProviderState);
        }

        jcrResourceProvider.deactivate();

        if (explicitSession != null) {
            explicitSession.logout();
        }

        footInDoor.logout();
    }

    @Test
    public void returnedSessionIsLive() {
        assertTrue(jcrProviderState.getSession().isLive());
    }

    @Test
    public void sessionUsesCorrectUser() {
        String expectedUser = useSudo ? SUDO_USER : AUTH_USER;
        assertEquals(expectedUser, jcrProviderState.getSession().getUserID());
    }

    @Test
    public void explicitSessionNotClosedOnLogout() {
        assumeTrue(loginStyle == LoginStyle.SESSION);

        jcrResourceProvider.logout(jcrProviderState);

        assertTrue(explicitSession.isLive());
    }

    @Test
    public void sessionsDoNotLeak() {
        // This test is only valid if we either didn't pass an explicit session,
        // or the provider had to clone it. Sessions created by the provider
        // must be closed by the provider, or we have a session leak.
        assumeThat(jcrProviderState.getSession(), is(not(sameInstance(explicitSession))));

        jcrResourceProvider.logout(jcrProviderState);

        assertFalse(jcrProviderState.getSession().isLive());
    }

    @Test
    public void impersonatorIsReportedCorrectly() {
        assumeTrue(useSudo);

        @SuppressWarnings("unchecked")
        ResolveContext<JcrProviderState> mockContext = mock(ResolveContext.class);
        when(mockContext.getProviderState()).thenReturn(jcrProviderState);
        Object reportedImpersonator = jcrResourceProvider.getAttribute(mockContext, ResourceResolver.USER_IMPERSONATOR);

        assertEquals(AUTH_USER, reportedImpersonator);
    }

    @Test
    public void clonesAreIndependent() {
        assumeTrue(loginStyle == LoginStyle.SESSION && doClone);

        assertNotSame(explicitSession, jcrProviderState.getSession());
    }

}
