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

import static java.util.Arrays.asList;
import static org.apache.sling.resourceresolver.impl.MockedResourceResolverImplTest.createRPHandler;
import static org.apache.sling.resourceresolver.impl.ResourceResolverImpl.PROP_REDIRECT_INTERNAL;
import static org.apache.sling.resourceresolver.impl.mapping.MapEntries.PROP_REDIRECT_EXTERNAL;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.path.Path;
import org.apache.sling.resourceresolver.impl.CommonResourceResolverFactoryImpl;
import org.apache.sling.resourceresolver.impl.ResourceAccessSecurityTracker;
import org.apache.sling.resourceresolver.impl.ResourceResolverFactoryActivator;
import org.apache.sling.resourceresolver.impl.ResourceResolverFactoryImpl;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderHandler;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderStorage;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
import org.apache.sling.resourceresolver.util.MockTestUtil;
import org.apache.sling.resourceresolver.util.MockTestUtil.ExpectedEtcMapping;
import org.apache.sling.serviceusermapping.ServiceUserMapper;
import org.apache.sling.spi.resource.provider.ResolveContext;
import org.apache.sling.spi.resource.provider.ResourceContext;
import org.apache.sling.spi.resource.provider.ResourceProvider;
import org.junit.Test;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

/**
 * These tests are for the /etc/map setup of the Map Entries when
 * an /etc/map is present.
 */
public class EtcMappingMapEntriesTest extends AbstractMappingMapEntriesTest {

    @Test
    public void root_node_to_content_mapping() throws Exception {
        setupEtcMapResource("localhost.8080", http,PROP_REDIRECT_EXTERNAL, "/content/simple-node");

        mapEntries.doInit();
        ExpectedEtcMapping expectedEtcMapping = new ExpectedEtcMapping("^http/localhost.8080/", "/content/simple-node/");
        expectedEtcMapping.assertEtcMap("Etc Mapping for simple node", mapEntries.getResolveMaps());
    }

    @Test
    public void match_to_content_mapping() throws Exception {
        setupEtcMapResource("test-node", http,
            PROP_REG_EXP, "localhost.8080/",
            PROP_REDIRECT_EXTERNAL, "/content/simple-match/"
        );

        mapEntries.doInit();
        ExpectedEtcMapping expectedEtcMapping = new ExpectedEtcMapping("^http/localhost.8080/", "/content/simple-match/");
        expectedEtcMapping.assertEtcMap("Etc Mapping for simple match", mapEntries.getResolveMaps());
    }

    // The following tests are based on the example from the https://sling.apache.org/documentation/the-sling-engine/mappings-for-resource-resolution.html page

    @Test
    public void internal_to_external_node_mapping() throws Exception {
        setupEtcMapResource("example.com.80", http,PROP_REDIRECT_EXTERNAL, "http://www.example.com/");

        mapEntries.doInit();
        ExpectedEtcMapping expectedEtcMapping = new ExpectedEtcMapping("^http/example.com.80/", "http://www.example.com/");
        expectedEtcMapping.assertEtcMap("Etc Mapping for internal to external based on node", mapEntries.getResolveMaps());
    }

    @Test
    public void internal_root_to_content_node_mapping() throws Exception {
        setupEtcMapResource("www.example.com.80", http,PROP_REDIRECT_INTERNAL, "/example");

        mapEntries.doInit();
        ExpectedEtcMapping expectedEtcMapping = new ExpectedEtcMapping().addEtcMapEntry("^http/www.example.com.80/", true, "/example/");
        expectedEtcMapping.assertEtcMap("Etc Mapping for internal root to content", mapEntries.getResolveMaps());
    }

    @Test
    public void host_redirect_match_mapping() throws Exception {
        setupEtcMapResource("any_example.com.80", http,
            PROP_REG_EXP, ".+\\.example\\.com\\.80",
            PROP_REDIRECT_EXTERNAL, "http://www.example.com/"
        );

        mapEntries.doInit();
        ExpectedEtcMapping expectedEtcMapping = new ExpectedEtcMapping().addEtcMapEntry("^http/.+\\.example\\.com\\.80", false, "http://www.example.com/");
        expectedEtcMapping.assertEtcMap("Etc Mapping for host redirect match mapping", mapEntries.getResolveMaps());
    }

    @Test
    public void nested_internal_mixed_mapping() throws Exception {
        Resource localhost = setupEtcMapResource("localhost_any", http,
            PROP_REG_EXP, "localhost\\.\\d*",
            PROP_REDIRECT_INTERNAL, "/content"
        );
        setupEtcMapResource("cgi-bin", localhost, PROP_REDIRECT_INTERNAL, "/scripts");
        setupEtcMapResource("gateway", localhost, PROP_REDIRECT_INTERNAL, "http://gbiv.com");
        setupEtcMapResource("(stories)", localhost, PROP_REDIRECT_INTERNAL, "/anecdotes/$1");

        mapEntries.doInit();
        ExpectedEtcMapping expectedEtcMapping = new ExpectedEtcMapping()
            .addEtcMapEntry("^http/localhost\\.\\d*", true, "/content")
            .addEtcMapEntry("^http/localhost\\.\\d*/cgi-bin/", true, "/scripts/")
            .addEtcMapEntry("^http/localhost\\.\\d*/gateway/", true, "http://gbiv.com/")
            .addEtcMapEntry("^http/localhost\\.\\d*/(stories)/", true, "/anecdotes/$1/");
        expectedEtcMapping.assertEtcMap("Etc Mapping for nested internal mixed mapping", mapEntries.getResolveMaps());

        // Not really an etc-map resource but it is good for now
        final Resource test = setupEtcMapResource("/scripts", "test");
        ResourceProvider<?> rp = new ResourceProvider<Object>() {
            @Override
            public Resource getResource(ResolveContext<Object> ctx, String path, ResourceContext rCtx, Resource parent) {
                if(path.equals("/scripts/test")) {
                    return test;
                }
                if(path.startsWith(map.getPath())) {
                    return findMapping(map, path);
                }
                return null;
            }

            private Resource findMapping(Resource parent, String path) {
                if(parent.getPath().equals(path)) {
                    return parent;
                }
                Iterator<Resource> i = parent.listChildren();
                while(i.hasNext()) {
                    Resource child = i.next();
                    if(path.equals(child.getPath())) {
                        return child;
                    } else {
                        return findMapping(child, path);
                    }
                }
                return null;
            }

            @Override
            public Iterator<Resource> listChildren(ResolveContext<Object> ctx, Resource parent) {
                if(parent.getPath().startsWith(map.getPath())) {
                    return parent.listChildren();
                }
                return null;
            }
        };

        List<ResourceProviderHandler> handlers = asList(createRPHandler(rp, "rp1", 0, "/"));
        ResourceProviderTracker resourceProviderTracker = mock(ResourceProviderTracker.class);
        ResourceProviderStorage storage = new ResourceProviderStorage(handlers);
        when(resourceProviderTracker.getResourceProviderStorage()).thenReturn(storage);
        ResourceResolverFactoryActivator activator = spy(new ResourceResolverFactoryActivator());
        // Both 'resourceProviderTracker' and 'resourceAccessSecurityTracker' are package private and so we cannot
        // set them here. Intercept the call to obtain them and provide the desired value
        when(activator.getResourceProviderTracker()).thenReturn(resourceProviderTracker);
        when(activator.getResourceAccessSecurityTracker()).thenReturn(new ResourceAccessSecurityTracker());
        when(activator.getBundleContext()).thenReturn(bundleContext);
        when(activator.getStringInterpolationProvider()).thenReturn(stringInterpolationProvider);
        when(activator.getMapRoot()).thenReturn("/etc/map");
        when(activator.getObservationPaths()).thenReturn(new Path[] {new Path("/")});
        CommonResourceResolverFactoryImpl commonFactory = spy(new CommonResourceResolverFactoryImpl(activator));
        when(bundleContext.getBundle()).thenReturn(bundle);
        ServiceUserMapper serviceUserMapper = mock(ServiceUserMapper.class);
        when(activator.getServiceUserMapper()).thenReturn(serviceUserMapper);
        when(serviceUserMapper.getServiceUserID(any(Bundle.class),anyString())).thenReturn("mapping");
        Method method = CommonResourceResolverFactoryImpl.class.getDeclaredMethod("activate", BundleContext.class);
        method.setAccessible(true);
        method.invoke(commonFactory, bundleContext);
        final Bundle usingBundle = mock(Bundle.class);
        ResourceResolverFactoryImpl resFac = new ResourceResolverFactoryImpl(commonFactory, usingBundle, null);
        ResourceResolver resResolver = resFac.getAdministrativeResourceResolver(null);
        when(activator.getPathToUriMappingService()).thenReturn(MockTestUtil.createPathToUriMappingServiceMock(resResolver));
        HttpServletRequest request = mock(HttpServletRequest.class);
        when(request.getScheme()).thenReturn("http");
        when(request.getServerName()).thenReturn("localhost");
        when(request.getServerPort()).thenReturn(80);
        Resource mappedResource = resResolver.resolve(request, "/cgi-bin/test.html");
        String path = mappedResource.getPath();
        assertEquals("Wrong Resolved Path", "/scripts/test", path);
    }

//    @Test
//    public void regex_map_internal_mapping() throws Exception {
//        setupEtcMapResource("regexmap", http,
//            PROP_REG_EXP, "$1.example.com/$2",
//            PROP_REDIRECT_INTERNAL, "/content/([^/]+)/(.*)"
//        );
//
//        mapEntries.doInit();
//        // Regex Mappings are ignored for the Resolve Map
//        ExpectedEtcMapping expectedEtcMapping = new ExpectedEtcMapping();
////            .addEtcMapEntry("^http/$1.example.com/$2", true, "/content/([^/]+)/(.*)");
//        expectedEtcMapping.assertEtcMap("Etc Mapping for regex map internal mapping", mapEntries.getResolveMaps());
//
//        ResourceProvider<?> rp = new ResourceProvider<Object>() {
//
//            @Override
//            public Resource getResource(ResolveContext<Object> ctx, String path, ResourceContext rCtx, Resource parent) {
//                return null;
//            }
//
//            @Override
//            public Iterator<Resource> listChildren(ResolveContext<Object> ctx, Resource parent) {
//                return null;
//            }
//        };
//
//        List<ResourceProviderHandler> handlers = asList(createRPHandler(rp, "rp1", 0, "/"));
//        ResourceProviderTracker resourceProviderTracker = mock(ResourceProviderTracker.class);
//        ResourceProviderStorage storage = new ResourceProviderStorage(handlers);
//        when(resourceProviderTracker.getResourceProviderStorage()).thenReturn(storage);
//        ResourceResolverFactoryActivator activator = spy(new ResourceResolverFactoryActivator());
//        when(activator.getResourceProviderTracker()).thenReturn(resourceProviderTracker);
////        activator.resourceProviderTracker = resourceProviderTracker;
//        when(activator.getResourceAccessSecurityTracker()).thenReturn(new ResourceAccessSecurityTracker());
////        activator.resourceAccessSecurityTracker = new ResourceAccessSecurityTracker();
//        CommonResourceResolverFactoryImpl commonFactory = new CommonResourceResolverFactoryImpl(activator);
//        final Bundle usingBundle = mock(Bundle.class);
//        ResourceResolverFactoryImpl resFac = new ResourceResolverFactoryImpl(commonFactory, usingBundle, null);
//        ResourceResolver resResolver = resFac.getAdministrativeResourceResolver(null);
//
//        HttpServletRequest request = mock(HttpServletRequest.class);
//        when(request.getScheme()).thenReturn("http");
//        when(request.getServerName()).thenReturn("a.example.com");
//        when(request.getServerPort()).thenReturn(80);
//        Resource mappedResource = resResolver.resolve(request, "/b.html");
//        String path = mappedResource.getPath();
//    }
}
