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

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.MockitoAnnotations.initMocks;

import java.util.Arrays;

import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;

public class ResourceTypePatternTest {
    
    private static final String TEST_PATH = "/content/path/to/test";
    
    private static final String RESOURCE_TYPE_TEST_PATH = "myproj/comp1";
    private static final String RESOURCE_TYPE_SUB1 = "myproj/comp2";
    private static final String RESOURCE_TYPE_SUB2 = "myproj/comp3";
    private static final String RESOURCE_TYPE_SUB3 = "myproj/comp4";
    private static final String RESOURCE_TYPE_SUBSUB1 = "myproj/comp5";
    
    private static final String RESOURCE_TYPE_OUTSIDE_SCOPE = "myproj/outsidescope";
    
    private static final String TEST_NODE_SUB1 = "subfolder1";        
    private static final String TEST_NODE_SUB2 = "subfolder2";
    private static final String TEST_NODE_SUB3 = "subfolder3";
    private static final String TEST_NODE_SUBSUB1 = "subsubfolder1";
    private static final String TEST_NODE_SUBSUB2 = "subsubfolder2";

    @Mock
    private Tree testTree;
    
    @Mock
    private Tree testTreeSub1;    
   
    @Mock
    private Tree testTreeSub2;

    @Mock
    private Tree testTreeSub3;
    
    @Mock
    private Tree testTreeSub3Sub1;
    
    @Mock
    private Tree testTreeSub3Sub2;
    
    @Mock
    private Tree testTreeParentOutsideScope;
    
    
    private ResourceTypePattern resourceTypePattern;
    

    @Before
    public void setup() {
        initMocks(this);
        
        setupTreeMock(testTreeParentOutsideScope, StringUtils.substringBeforeLast(TEST_PATH, "/"), null, RESOURCE_TYPE_OUTSIDE_SCOPE);
        setupTreeMock(testTree, StringUtils.substringAfterLast(TEST_PATH, "/"), testTreeParentOutsideScope, RESOURCE_TYPE_TEST_PATH);

        setupTreeMock(testTreeSub1, TEST_NODE_SUB1, testTree, RESOURCE_TYPE_SUB1);
        setupTreeMock(testTreeSub2, TEST_NODE_SUB2, testTree, RESOURCE_TYPE_SUB2);
        setupTreeMock(testTreeSub3, TEST_NODE_SUB3, testTree, RESOURCE_TYPE_SUB3);

        setupTreeMock(testTreeSub3Sub1, TEST_NODE_SUBSUB1, testTreeSub3, RESOURCE_TYPE_SUBSUB1);
        setupTreeMock(testTreeSub3Sub2, TEST_NODE_SUBSUB2, testTreeSub3, RESOURCE_TYPE_SUBSUB1);
        
    }



    @Test
    public void testBasicMatchWithoutChildren() {
        
        resourceTypePattern = new ResourceTypePattern(Arrays.asList(RESOURCE_TYPE_TEST_PATH, RESOURCE_TYPE_SUB1, RESOURCE_TYPE_SUB3), TEST_PATH, false);
        
        assertNonTreeFunctionsReturnFalse();
        
        assertTrue(resourceTypePattern.matches(testTree, null));
        assertTrue(resourceTypePattern.matches(testTreeSub1, null));
        assertFalse(resourceTypePattern.matches(testTreeSub2, null));
        assertTrue(resourceTypePattern.matches(testTreeSub3, null));
        assertFalse(resourceTypePattern.matches(testTreeSub3Sub1, null));
        assertFalse(resourceTypePattern.matches(testTreeSub3Sub2, null));

    }
    
    @Test
    public void testMatchWithoutChildren() {
        
        String restrictionWithPath = RESOURCE_TYPE_SUB2+"@"+TEST_NODE_SUB2;
        resourceTypePattern = new ResourceTypePattern(Arrays.asList(restrictionWithPath, RESOURCE_TYPE_SUB3), TEST_PATH, false);
        
        assertNonTreeFunctionsReturnFalse();
        
        assertTrue("Has to match because of @path usage "+restrictionWithPath, resourceTypePattern.matches(testTree, null));
        assertFalse(resourceTypePattern.matches(testTreeSub1, null));
        assertFalse("Must not match (although it has "+RESOURCE_TYPE_SUB2+", it does not have a child '"+TEST_NODE_SUB2+"' with this resource type)", resourceTypePattern.matches(testTreeSub2, null));
        assertTrue("Has to match because of "+RESOURCE_TYPE_SUB3+" in list", resourceTypePattern.matches(testTreeSub3, null));
        assertFalse(resourceTypePattern.matches(testTreeSub3Sub1, null));
        assertFalse(resourceTypePattern.matches(testTreeSub3Sub2, null));
    }
    
    @Test
    public void testMatchWithChildren() {
        
        resourceTypePattern = new ResourceTypePattern(Arrays.asList(RESOURCE_TYPE_SUB3), TEST_PATH, true);
        
        assertNonTreeFunctionsReturnFalse();
        
        assertFalse("Not a node at or below "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTree, null));
        assertFalse("Not a node at or below "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTreeSub1, null));
        assertFalse("Not a node at or below "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTreeSub2, null));
        assertTrue("The node with "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTreeSub3, null));
        assertTrue("A node below a node with "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTreeSub3Sub1, null));
        assertTrue("A node below a node with "+RESOURCE_TYPE_SUB3, resourceTypePattern.matches(testTreeSub3Sub2, null));
    }
    
    @Test
    public void testMatchWithChildrenDoesNotLeaveBasePath() {
        
        resourceTypePattern = new ResourceTypePattern(Arrays.asList(RESOURCE_TYPE_OUTSIDE_SCOPE), TEST_PATH, true);
        
        assertNonTreeFunctionsReturnFalse();
        
        // all false as RESOURCE_TYPE_OUTSIDE_SCOPE is only found above TEST_PATH
        assertFalse(resourceTypePattern.matches(testTree, null));
        assertFalse(resourceTypePattern.matches(testTreeSub1, null));
        assertFalse(resourceTypePattern.matches(testTreeSub2, null));
        assertFalse(resourceTypePattern.matches(testTreeSub3, null));
        assertFalse(resourceTypePattern.matches(testTreeSub3Sub1, null));
        assertFalse(resourceTypePattern.matches(testTreeSub3Sub2, null));
    }
    
    @Test
    public void testMatchWithChildrenAndPathUsage() {
        
        String restrictionWithPath = RESOURCE_TYPE_SUBSUB1+"@"+TEST_NODE_SUBSUB1;
        resourceTypePattern = new ResourceTypePattern(Arrays.asList(restrictionWithPath), TEST_PATH, true);
        
        assertNonTreeFunctionsReturnFalse();
        
        assertFalse("This node or any of its parents do not have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1, resourceTypePattern.matches(testTree, null));
        assertFalse("This node or any of its parents do not have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1, resourceTypePattern.matches(testTreeSub1, null));
        assertFalse("This node or any of its parents do not have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1,resourceTypePattern.matches(testTreeSub2, null));
        assertTrue("This node does have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1, resourceTypePattern.matches(testTreeSub3, null));
        assertTrue("A node in parent hierarchy does have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1, resourceTypePattern.matches(testTreeSub3Sub1, null));
        assertTrue("A node in parent hierarchy does have a sub node '"+TEST_NODE_SUBSUB1+"' with "+RESOURCE_TYPE_SUBSUB1, resourceTypePattern.matches(testTreeSub3Sub2, null));
    }
    

    private void assertNonTreeFunctionsReturnFalse() {
        assertFalse(resourceTypePattern.matches(TEST_PATH));
        assertFalse(resourceTypePattern.matches());
    }

    private void setupTreeMock(Tree tree, String path, Tree parentTree, String resourceType) {

        doReturn(parentTree==null).when(tree).isRoot();
        doReturn(parentTree).when(tree).getParent();
        
        mockGetStringProperty(tree, ResourceTypePattern.SLING_RESOURCE_TYPE, resourceType);
        
        String effectivePath = path;
        if(parentTree!=null) {
            effectivePath = parentTree.getPath() + "/" + path;
            String childNodeName = StringUtils.substringAfterLast(effectivePath, "/");
            doReturn(tree).when(parentTree).getChild(childNodeName);
        }
        doReturn(effectivePath).when(tree).getPath();
        
        // default for getChild
        doThrow(new IllegalArgumentException()).when(tree).getChild(Mockito.anyString());
        
    }
    
    private void mockGetStringProperty(Tree tree, String propertyName, String value) {
        PropertyState propertyState = mock(PropertyState.class);
        doReturn(propertyState).when(tree).getProperty(propertyName);
        doReturn(false).when(propertyState).isArray();
        doReturn(value).when(propertyState).getValue(Type.STRING);
    }
}
