/*
 * 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.jackrabbit.oak.plugins.nodetype;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Lists.newArrayList;
import static javax.jcr.PropertyType.UNDEFINED;
import static org.apache.jackrabbit.JcrConstants.NT_BASE;

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

import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;

import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.plugins.value.jcr.PartialValueFactory;
import org.apache.jackrabbit.oak.spi.nodetype.EffectiveNodeType;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;

/**
 * EffectiveNodeTypeImpl... TODO
 */
class EffectiveNodeTypeImpl implements EffectiveNodeType {

    private static final Logger log = LoggerFactory.getLogger(EffectiveNodeTypeImpl.class);

    private static final NodeTypeImpl[] NO_MIXINS = new NodeTypeImpl[0];

    private final Map<String, NodeTypeImpl> nodeTypes = Maps.newLinkedHashMap();

    private final ReadOnlyNodeTypeManager ntMgr;

    private final PartialValueFactory valueFactory;

    EffectiveNodeTypeImpl(
            NodeTypeImpl primary, NodeTypeImpl[] mixins,
            ReadOnlyNodeTypeManager ntMgr) {
        this.ntMgr = ntMgr;
        this.valueFactory = new PartialValueFactory(ntMgr.getNamePathMapper());

        addNodeType(checkNotNull(primary));
        for (NodeTypeImpl mixin : checkNotNull(mixins)) {
            addNodeType(mixin);
        }
        if (!nodeTypes.containsKey(NT_BASE)) {
            try {
                nodeTypes.put(
                        NT_BASE,
                        (NodeTypeImpl) ntMgr.getNodeType(NT_BASE)); // FIXME
            } catch (RepositoryException e) {
                // TODO: ignore/warning/error?
            }
        }
    }

    EffectiveNodeTypeImpl(NodeTypeImpl primary, ReadOnlyNodeTypeManager ntMgr) {
        this(primary, NO_MIXINS, ntMgr);
    }

    private void addNodeType(NodeTypeImpl type) {
        String name = type.getName();
        if (!nodeTypes.containsKey(name)) {
            nodeTypes.put(name, type);
            NodeType[] supertypes = type.getDeclaredSupertypes();
            for (NodeType supertype : supertypes) {
                addNodeType((NodeTypeImpl) supertype); // FIXME
            }
        }
    }

    /**
     * Determines whether this effective node type representation includes
     * (either through inheritance or aggregation) the given node type.
     *
     * @param nodeTypeName name of node type
     * @return {@code true} if the given node type is included, otherwise {@code false}.
     */
    @Override
    public boolean includesNodeType(String nodeTypeName) {
        return nodeTypes.containsKey(nodeTypeName);
    }


    /**
     * Determines whether this effective node type representation includes
     * (either through inheritance or aggregation) all of the given node types.
     *
     * @param nodeTypeNames array of node type names
     * @return {@code true} if all of the given node types are included,
     *         otherwise {@code false}
     */
    @Override
    public boolean includesNodeTypes(String[] nodeTypeNames) {
        for (String ntName : nodeTypeNames) {
            if (!includesNodeType(ntName)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Determines whether this effective node type supports adding
     * the specified mixin.
     * @param mixin name of mixin type
     * @return {@code true} if the mixin type is supported, otherwise {@code false}
     */
    @Override
    public boolean supportsMixin(String mixin) {
        if (includesNodeType(mixin)) {
            return true;
        }

        NodeType mixinType = null;
        try {
            mixinType = ntMgr.internalGetNodeType(mixin);
            if (!mixinType.isMixin() || mixinType.isAbstract()) {
                return false;
            }
        } catch (NoSuchNodeTypeException e) {
            log.debug("Unknown mixin type " + mixin);
        }

        return true;
    }

    @Override
    public Iterable<NodeDefinition> getNodeDefinitions() {
        List<NodeDefinition> definitions = new ArrayList<NodeDefinition>();
        for (NodeType nt : nodeTypes.values()) {
            definitions.addAll(((NodeTypeImpl) nt).internalGetChildDefinitions());
        }
        return definitions;
    }

    @Override
    public Iterable<PropertyDefinition> getPropertyDefinitions() {
        List<PropertyDefinition> definitions = new ArrayList<PropertyDefinition>();
        for (NodeType nt : nodeTypes.values()) {
            definitions.addAll(((NodeTypeImpl) nt).internalGetPropertyDefinitions());
        }
        return definitions;
    }

    @Override
    public Iterable<NodeDefinition> getAutoCreateNodeDefinitions() {
        return Iterables.filter(getNodeDefinitions(), new Predicate<NodeDefinition>() {
            @Override
            public boolean apply(NodeDefinition nodeDefinition) {
                return nodeDefinition.isAutoCreated();
            }
        });
    }

    @Override
    public Iterable<PropertyDefinition> getAutoCreatePropertyDefinitions() {
        return Iterables.filter(getPropertyDefinitions(), new Predicate<PropertyDefinition>() {
            @Override
            public boolean apply(PropertyDefinition propertyDefinition) {
                return propertyDefinition.isAutoCreated();
            }
        });
    }

    @Override
    public Iterable<NodeDefinition> getMandatoryNodeDefinitions() {
        return Iterables.filter(getNodeDefinitions(), new Predicate<NodeDefinition>() {
            @Override
            public boolean apply(NodeDefinition nodeDefinition) {
                return nodeDefinition.isMandatory();
            }
        });
    }

    @Override
    public Iterable<PropertyDefinition> getMandatoryPropertyDefinitions() {
        return Iterables.filter(getPropertyDefinitions(), new Predicate<PropertyDefinition>() {
            @Override
            public boolean apply(PropertyDefinition propertyDefinition) {
                return propertyDefinition.isMandatory();
            }
        });
    }

    /**
     * Return all node definitions that match the specified oak name.
     *
     * @param oakName An internal oak name.
     * @return All node definitions that match the given internal oak name.
     */
    @Override
    @NotNull
    public Iterable<NodeDefinition> getNamedNodeDefinitions(
            final String oakName) {
        return Iterables.concat(Iterables.transform(
                nodeTypes.values(),
                new Function<NodeTypeImpl, Iterable<NodeDefinition>>() {
                    @Override
                    public Iterable<NodeDefinition> apply(NodeTypeImpl input) {
                        return input.getDeclaredNamedNodeDefinitions(oakName);
                    }
                }));
    }

    /**
     * Return all property definitions that match the specified oak name.
     *
     * @param oakName An internal oak name.
     * @return All property definitions that match the given internal oak name.
     */
    @Override
    @NotNull
    public Iterable<PropertyDefinition> getNamedPropertyDefinitions(
            String oakName) {
        List<PropertyDefinition> definitions = newArrayList();
        for (NodeTypeImpl type : nodeTypes.values()) {
            definitions.addAll(type.getDeclaredNamedPropertyDefinitions(oakName));
        }
        return definitions;
    }

    /**
     * Return all residual node definitions.
     *
     * @return All residual node definitions.
     */
    @Override
    @NotNull
    public Iterable<NodeDefinition> getResidualNodeDefinitions() {
        List<NodeDefinition> definitions = newArrayList();
        for (NodeTypeImpl type : nodeTypes.values()) {
            definitions.addAll(type.getDeclaredResidualNodeDefinitions());
        }
        return definitions;
    }

    /**
     * Return all residual property definitions.
     *
     * @return All residual property definitions.
     */
    @Override
    @NotNull
    public Iterable<PropertyDefinition> getResidualPropertyDefinitions() {
        List<PropertyDefinition> definitions = newArrayList();
        for (NodeTypeImpl type : nodeTypes.values()) {
            definitions.addAll(type.getDeclaredResidualPropertyDefinitions());
        }
        return definitions;
    }

    @Override
    public void checkSetProperty(PropertyState property) throws RepositoryException {
        PropertyDefinition definition = getDefinition(property);
        if (definition.isProtected()) {
            return;
        }

        NodeType nt = definition.getDeclaringNodeType();
        if (definition.isMultiple()) {
            List<Value> values = valueFactory.createValues(property);
            if (!nt.canSetProperty(property.getName(), values.toArray(new Value[values.size()]))) {
                throw new ConstraintViolationException("Cannot set property '" + property.getName() + "' to '" + values + '\'');
            }
        } else {
            Value v = valueFactory.createValue(property);
            if (!nt.canSetProperty(property.getName(), v)) {
                throw new ConstraintViolationException("Cannot set property '" + property.getName() + "' to '" + v + '\'');
            }
        }
    }

    @Override
    public void checkRemoveProperty(PropertyState property) throws RepositoryException {
        PropertyDefinition definition = getDefinition(property);
        if (definition.isProtected()) {
            return;
        }

        if (!definition.getDeclaringNodeType().canRemoveProperty(property.getName())) {
            throw new ConstraintViolationException("Cannot remove property '" + property.getName() + '\'');
        }
    }

    @Override
    public void checkMandatoryItems(Tree tree) throws ConstraintViolationException {
        for (NodeType nodeType : nodeTypes.values()) {
            for (PropertyDefinition pd : nodeType.getPropertyDefinitions()) {
                String name = pd.getName();
                if (pd.isMandatory() && !pd.isProtected() && tree.getProperty(name) == null) {
                    throw new ConstraintViolationException(
                            "Property '" + name + "' in '" + nodeType.getName() + "' is mandatory");
                }
            }
            for (NodeDefinition nd : nodeType.getChildNodeDefinitions()) {
                String name = nd.getName();
                if (nd.isMandatory() && !nd.isProtected() && !tree.hasChild(name)) {
                    throw new ConstraintViolationException(
                            "Node '" + name + "' in '" + nodeType.getName() + "' is mandatory");
                }
            }
        }
    }

    @Override
    public void checkOrderableChildNodes() throws UnsupportedRepositoryOperationException {
        for (NodeType nt : nodeTypes.values()) {
            if (nt.hasOrderableChildNodes()) {
                return;
            }
        }

        throw new UnsupportedRepositoryOperationException("Child node ordering is not supported on this node");
    }

    /**
     * Calculates the applicable definition for the property with the specified
     * characteristics under a parent with this effective type.
     *
     * @param propertyName The internal oak name of the property for which the
     * definition should be retrieved.
     * @param isMultiple {@code true} if the target property is multi-valued.
     * @param type The target type of the property.
     * @param exactTypeMatch {@code true} if the required type of the definition
     * must exactly match the type of the target property.
     * @return the applicable definition for the target property.
     * @throws ConstraintViolationException If no matching definition can be found.
     */
    @Override
    public PropertyDefinition getPropertyDefinition(
            String propertyName, boolean isMultiple,
            int type, boolean exactTypeMatch)
            throws ConstraintViolationException {
       // TODO: This may need to be optimized
       for (PropertyDefinition def : getNamedPropertyDefinitions(propertyName)) {
           int defType = def.getRequiredType();
           if (isMultiple == def.isMultiple()
                   &&(!exactTypeMatch || (type == defType || UNDEFINED == type || UNDEFINED == defType))) {
               return def;
           }
       }

       // try if there is a residual definition
       for (PropertyDefinition def : getResidualPropertyDefinitions()) {
           int defType = def.getRequiredType();
           if (isMultiple == def.isMultiple()
                   && (!exactTypeMatch || (type == defType || UNDEFINED == type || UNDEFINED == defType))) {
               return def;
           }
       }

       throw new ConstraintViolationException(
               "No matching property definition found for " + propertyName);
   }

    /**
     * Calculates the applicable definition for the property with the specified
     * characteristics under a parent with this effective type.
     *
     * @param name The internal oak name of the property for which the definition should be retrieved.
     * @param type The target type of the property.
     * @param unknownMultiple {@code true} if the target property has an unknown type, {@code false} if it is known to be a multi-valued property.
     * @return the applicable definition for the target property or {@code null} if no matching definition can be found.
     */
    @Override
    public PropertyDefinition getPropertyDefinition(String name, int type, boolean unknownMultiple) {
        // TODO check multivalue handling
        Iterable<PropertyDefinition> definitions = getNamedPropertyDefinitions(name);

        for (PropertyDefinition def : definitions) {
            int requiredType = def.getRequiredType();
            if ((requiredType == PropertyType.UNDEFINED || type == PropertyType.UNDEFINED || requiredType == type)
                    && (def.isMultiple() || unknownMultiple)) {
                return def;
            }
        }
        definitions = getResidualPropertyDefinitions();
        for (PropertyDefinition def : definitions) {
            int requiredType = def.getRequiredType();
            if ((requiredType == PropertyType.UNDEFINED || type == PropertyType.UNDEFINED || requiredType == type)
                    && !def.isMultiple() && unknownMultiple) {
                return def;
            }
        }
        for (PropertyDefinition def : definitions) {
            int requiredType = def.getRequiredType();
            if ((requiredType == PropertyType.UNDEFINED || type == PropertyType.UNDEFINED || requiredType == type)
                    && def.isMultiple()) {
                return def;
            }
        }
        return null;
    }

    /**
     *
     * @param childName The internal oak name of the target node.
     * @param childEffective
     * @return the node definition
     * @throws ConstraintViolationException
     */
    @Override
    public NodeDefinition getNodeDefinition(
            String childName, EffectiveNodeType childEffective)
            throws ConstraintViolationException {
       for (NodeDefinition def : getNamedNodeDefinitions(childName)) {
           boolean match = true;
           if (childEffective != null && !childEffective.includesNodeTypes(def.getRequiredPrimaryTypeNames())) {
               match = false;
           }
           if (match) {
               return def;
           }
       }

       for (NodeDefinition def : getResidualNodeDefinitions()) {
           boolean match = true;
           if (childEffective != null && !childEffective.includesNodeTypes(def.getRequiredPrimaryTypeNames())) {
               match = false;
           }
           if (match) {
               return def;
           }
       }

       throw new ConstraintViolationException(
               "No matching node definition found for " + childName);
   }

    //------------------------------------------------------------< private >---

    private PropertyDefinition getDefinition(PropertyState property) throws RepositoryException {
        String propertyName = property.getName();
        int propertyType = property.getType().tag();
        boolean isMultiple = property.isArray();

        return getPropertyDefinition(propertyName, isMultiple, propertyType, true);
    }

}
