/*
 * 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 java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionPattern;
import org.apache.sling.api.SlingConstants;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Implementation of the {@link RestrictionPattern} interface that returns {@code true} if the resource type of the target tree (or the
 * parent of a target property) is contained in the configured resource type. */
public class ResourceTypePattern implements RestrictionPattern {
    private static final Logger LOG = LoggerFactory.getLogger(ResourceTypePattern.class);

    static final String DEFAULT_PATH = ".";
    static final String PATH_MARKER = "@";
    
    static final String SLING_RESOURCE_TYPE = SlingConstants.NAMESPACE_PREFIX + ":" + SlingConstants.PROPERTY_RESOURCE_TYPE;


    private final String limitedToPath;
    private final boolean matchChildren;
    
    private final Map<String,Set<String>> resourceTypesByPath;
    
  
    ResourceTypePattern(@NotNull Iterable<String> resourceTypesRaw, String limitedToPath, boolean matchChildren) {
        
        this.limitedToPath = limitedToPath;
        this.matchChildren = matchChildren;
        
        Map<String,Set<String>> resourceTypesByPath = new LinkedHashMap<String,Set<String>>();
        for (String resourceTypeRaw : resourceTypesRaw) {
            String path;
            String resourceType;
            if(resourceTypeRaw.contains(PATH_MARKER)) {
                String[] bits = resourceTypeRaw.trim().split(PATH_MARKER, 2);
                path = bits[1];
                resourceType = bits[0];
            } else {
                path = DEFAULT_PATH;
                resourceType = resourceTypeRaw;
            }
                
            Set<String> resourceTypesForPath = resourceTypesByPath.get(path);
            if(resourceTypesForPath==null) {
                resourceTypesForPath = new HashSet<String>();
                resourceTypesByPath.put(path, resourceTypesForPath);
            }
            resourceTypesForPath.add(resourceType);
        }
        
        this.resourceTypesByPath = Collections.unmodifiableMap(resourceTypesByPath);
        LOG.trace("pattern setup with resourceTypesByPath={}",  this.resourceTypesByPath);
    }
    
    String getLimitedToPath() {
        return limitedToPath;
    }

    boolean isMatchChildren() {
        return matchChildren;
    }

    @Override
    public boolean matches(@NotNull Tree tree, @Nullable PropertyState property) {
        boolean isMatch = matchesAtTree(tree);
        if(!isMatch && matchChildren) { // try parent hierarchy
            Tree treeCursor = tree;
            while(!isMatch && !treeCursor.isRoot()) {
                treeCursor = treeCursor.getParent();
                if(!treeCursor.getPath().startsWith(limitedToPath)) {
                    if(LOG.isTraceEnabled()) {
                        LOG.trace("Breaking parent traversal loop: tree={}, limitedToPath={}", treeCursor.getPath(), limitedToPath);
                    }
                    break; 
                }
                isMatch = matchesAtTree(treeCursor);
            }
        }
        if(LOG.isDebugEnabled()) {
            LOG.debug("Match for "+tree.getPath()+": "+ (isMatch ? "YES":"NO") + " ("+this+")");
        }
        return isMatch;
    }

    private boolean matchesAtTree(Tree tree) {
        boolean isResourceTypeMatch = false;
        for (String path : resourceTypesByPath.keySet()) {

                Tree treeToCheck = tree; // the default if e.g. just the resource type without @path is given
                if(!DEFAULT_PATH.equals(path)) {
                    try {
                        String[] segments = path.split("/");
                        for (String string : segments) {
                            treeToCheck = treeToCheck.getChild(string);
                        }
                    } catch (IllegalArgumentException e) {
                        continue; // continue and ignore if path is not found
                    } 
                }
                
                Set<String> resourceTypesForPath = resourceTypesByPath.get(path);
                String actualResourceType = getResourceTypeFromTree(treeToCheck);
                isResourceTypeMatch = resourceTypesForPath.contains(actualResourceType);
                
                if(LOG.isTraceEnabled()) {
                    LOG.trace("isResourceTypeMatch={} (checked at path {} at sub path {})", new Object[]{isResourceTypeMatch, tree.getPath(), path});
                }
                if(isResourceTypeMatch) {
                    break; // return as quickly as possible
                }

        }
        return isResourceTypeMatch;
    }

    public String getResourceTypeFromTree(Tree treeToCheck) {
        PropertyState property = treeToCheck.getProperty(SLING_RESOURCE_TYPE);
        return property != null && !property.isArray() ? property.getValue(Type.STRING) : null;
    }

    @Override
    public boolean matches(@NotNull String path) {
        return false;
    }

    @Override
    public boolean matches() {
        // node type pattern never matches for repository level permissions
        return false;
    }

    // -------------------------------------------------------------< Object >---

    @Override
    public String toString() {
        return "ResourceTypePattern [limitedToPath=" + limitedToPath + ", matchChildren=" + matchChildren + ", resourceTypesByPath="
                + resourceTypesByPath + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((limitedToPath == null) ? 0 : limitedToPath.hashCode());
        result = prime * result + (matchChildren ? 1231 : 1237);
        result = prime * result + ((resourceTypesByPath == null) ? 0 : resourceTypesByPath.hashCode());
        return result;
    }


    @Override
    public boolean equals(Object obj) {
        if(this == obj)
            return true;
        if(obj == null)
            return false;
        if(getClass() != obj.getClass())
            return false;
        ResourceTypePattern other = (ResourceTypePattern) obj;
        if(limitedToPath == null) {
            if(other.limitedToPath != null)
                return false;
        } else if(!limitedToPath.equals(other.limitedToPath))
            return false;
        if(matchChildren != other.matchChildren)
            return false;
        if(resourceTypesByPath == null) {
            if(other.resourceTypesByPath != null)
                return false;
        } else if(!resourceTypesByPath.equals(other.resourceTypesByPath))
            return false;
        return true;
    }
    
}
