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

import static org.apache.jackrabbit.JcrConstants.JCR_CHILDNODEDEFINITION;
import static org.apache.jackrabbit.JcrConstants.JCR_HASORDERABLECHILDNODES;
import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
import static org.apache.jackrabbit.JcrConstants.JCR_NODETYPENAME;
import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYITEMNAME;
import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import static org.apache.jackrabbit.JcrConstants.JCR_PROPERTYDEFINITION;
import static org.apache.jackrabbit.JcrConstants.JCR_SUPERTYPES;
import static org.apache.jackrabbit.JcrConstants.NT_CHILDNODEDEFINITION;
import static org.apache.jackrabbit.JcrConstants.NT_NODETYPE;
import static org.apache.jackrabbit.JcrConstants.NT_PROPERTYDEFINITION;
import static org.apache.jackrabbit.oak.api.Type.NAME;
import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_ABSTRACT;
import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_QUERYABLE;

import java.util.Arrays;
import java.util.List;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeDefinitionTemplate;
import javax.jcr.nodetype.NodeTypeDefinition;
import javax.jcr.nodetype.NodeTypeExistsException;
import javax.jcr.nodetype.NodeTypeTemplate;
import javax.jcr.nodetype.PropertyDefinition;
import javax.jcr.nodetype.PropertyDefinitionTemplate;

import com.google.common.collect.Lists;

import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.namepath.NameMapper;

class NodeTypeTemplateImpl extends NamedTemplate implements NodeTypeTemplate {

    private static final PropertyDefinition[] EMPTY_PROPERTY_DEFINITION_ARRAY =
            new PropertyDefinition[0];

    private static final NodeDefinition[] EMPTY_NODE_DEFINITION_ARRAY =
            new NodeDefinition[0];

    protected boolean isMixin;

    protected boolean isOrderable;

    protected boolean isAbstract;

    protected boolean queryable;

    private String primaryItemOakName = null; // not defined by default

    @Nonnull
    private String[] superTypeOakNames = new String[0];

    private List<PropertyDefinitionTemplateImpl> propertyDefinitionTemplates = null;

    private List<NodeDefinitionTemplateImpl> nodeDefinitionTemplates = null;

    NodeTypeTemplateImpl(@Nonnull NameMapper mapper) {
        super(mapper);
    }

    NodeTypeTemplateImpl(@Nonnull NameMapper mapper, @Nonnull NodeTypeDefinition definition)
            throws ConstraintViolationException {
        super(mapper, definition.getName());

        setMixin(definition.isMixin());
        setOrderableChildNodes(definition.hasOrderableChildNodes());
        setAbstract(definition.isAbstract());
        setQueryable(definition.isQueryable());
        String primaryItemName = definition.getPrimaryItemName();
        if (primaryItemName != null) {
            setPrimaryItemName(primaryItemName);
        }
        setDeclaredSuperTypeNames(definition.getDeclaredSupertypeNames());

        PropertyDefinition[] pds = definition.getDeclaredPropertyDefinitions();
        if (pds != null) {
            propertyDefinitionTemplates =
                    Lists.newArrayListWithCapacity(pds.length);
            for (PropertyDefinition pd : pds) {
                propertyDefinitionTemplates.add(
                        new PropertyDefinitionTemplateImpl(mapper, pd));
            }
        }

        NodeDefinition[] nds = definition.getDeclaredChildNodeDefinitions();
        if (nds != null) {
            nodeDefinitionTemplates =
                    Lists.newArrayListWithCapacity(nds.length);
            for (NodeDefinition nd : nds) {
                nodeDefinitionTemplates.add(
                        new NodeDefinitionTemplateImpl(mapper, nd));
            }
        }
    }

    /**
     * Writes this node type as an {@code nt:nodeType} child of the given
     * parent node. An exception is thrown if the child node already exists,
     * unless the {@code allowUpdate} flag is set, in which case the existing
     * node is overwritten.
     *
     * @param parent parent node under which to write this node type
     * @param allowUpdate whether to overwrite an existing type
     * @return The node type tree.
     * @throws RepositoryException if this type could not be written
     */
    Tree writeTo(@Nonnull Tree parent, boolean allowUpdate) throws RepositoryException {
        String oakName = getOakName();
        if (oakName == null) {
            throw new RepositoryException("Cannot register node type: name is missing.");
        }

        Tree type = parent.getChild(oakName);
        if (!type.exists()) {
            type = parent.addChild(oakName);
            type.setProperty(JCR_PRIMARYTYPE, NT_NODETYPE, Type.NAME);
        } else if (!allowUpdate) {
            throw new NodeTypeExistsException(
                    "Node type " + getName() + " already exists");
        }

        type.setProperty(JCR_NODETYPENAME, oakName, Type.NAME);

        if (superTypeOakNames.length > 0) {
            type.setProperty(
                    JCR_SUPERTYPES,
                    Arrays.asList(superTypeOakNames), Type.NAMES);
        } else {
            type.removeProperty(JCR_SUPERTYPES);
        }

        type.setProperty(JCR_IS_ABSTRACT, isAbstract);
        type.setProperty(JCR_IS_QUERYABLE, queryable);
        type.setProperty(JCR_ISMIXIN, isMixin);

        // TODO fail (in validator?) if not orderable but a supertype is orderable
        // See 3.7.6.7 Node Type Attribute Subtyping Rules (OAK-411)
        type.setProperty(JCR_HASORDERABLECHILDNODES, isOrderable);

        // TODO fail (in validator?) if a supertype specifies a different primary item
        // See 3.7.6.7 Node Type Attribute Subtyping Rules (OAK-411)
        if (primaryItemOakName != null) {
            type.setProperty(JCR_PRIMARYITEMNAME, primaryItemOakName, Type.NAME);
        } else {
            type.removeProperty(JCR_PRIMARYITEMNAME);
        }

        // TODO fail (in validator?) on invalid item definitions
        // See 3.7.6.8 Item Definitions in Subtypes (OAK-411)
        writeItemDefinitions(type, propertyDefinitionTemplates, JCR_PROPERTYDEFINITION, NT_PROPERTYDEFINITION);
        writeItemDefinitions(type, nodeDefinitionTemplates, JCR_CHILDNODEDEFINITION, NT_CHILDNODEDEFINITION);

        return type;
    }

    private static void writeItemDefinitions(@Nonnull Tree nodeTypeTree, @CheckForNull List<? extends ItemDefinitionTemplate> itemDefTemplates,
                                             @Nonnull String nodeName, @Nonnull String primaryTypeName) throws RepositoryException {
        Tree tree;
        int index = 1;
        if (itemDefTemplates != null) {
            for (ItemDefinitionTemplate template : itemDefTemplates) {
                String name = nodeName(nodeName, index);
                tree = nodeTypeTree.getChild(name);
                if (!tree.exists()) {
                    tree = nodeTypeTree.addChild(name);
                    tree.setProperty(
                            JCR_PRIMARYTYPE, primaryTypeName, NAME);
                }
                template.writeTo(tree);
                index++;
            }
        }
        tree = nodeTypeTree.getChild(nodeName(nodeName, index++));
        while (tree.exists()) {
            tree.remove();
            tree = nodeTypeTree.getChild(nodeName(nodeName, index++));
        }
    }

    private static String nodeName(String name, int index) {
        return (index == 1) ? name : name + '[' + index + ']';
    }

    //------------------------------------------------------------< public >--

    @Override
    public boolean isMixin() {
        return isMixin;
    }

    @Override
    public void setMixin(boolean mixin) {
        this.isMixin = mixin;
    }

    @Override
    public boolean hasOrderableChildNodes() {
        return isOrderable ;
    }

    @Override
    public void setOrderableChildNodes(boolean orderable) {
        this.isOrderable = orderable;
    }

    @Override
    public boolean isAbstract() {
        return isAbstract;
    }

    @Override
    public void setAbstract(boolean abstractStatus) {
        this.isAbstract = abstractStatus;
    }

    @Override
    public boolean isQueryable() {
        return queryable;
    }

    @Override
    public void setQueryable(boolean queryable) {
        this.queryable = queryable;
    }

    @Override
    public String getPrimaryItemName() {
        return getJcrNameAllowNull(primaryItemOakName);
    }

    @Override
    public void setPrimaryItemName(String jcrName)
            throws ConstraintViolationException {
        this.primaryItemOakName =
                getOakNameAllowNullOrThrowConstraintViolation(jcrName);
    }

    @Override
    public String[] getDeclaredSupertypeNames() {
        return getJcrNamesAllowNull(superTypeOakNames);
    }

    @Override
    public void setDeclaredSuperTypeNames(String[] jcrNames)
            throws ConstraintViolationException {
        this.superTypeOakNames =
                getOakNamesOrThrowConstraintViolation(jcrNames);
    }

    @Override
    public PropertyDefinition[] getDeclaredPropertyDefinitions() {
        if (propertyDefinitionTemplates != null) {
            return propertyDefinitionTemplates.toArray(
                    EMPTY_PROPERTY_DEFINITION_ARRAY);
        } else {
            return null;
        }
    }

    @Override
    public List<? extends PropertyDefinitionTemplate> getPropertyDefinitionTemplates() {
        if (propertyDefinitionTemplates == null) {
            propertyDefinitionTemplates = Lists.newArrayList();
        }
        return propertyDefinitionTemplates;
    }

    @Override
    public NodeDefinition[] getDeclaredChildNodeDefinitions() {
        if (nodeDefinitionTemplates != null) {
            return nodeDefinitionTemplates.toArray(
                    EMPTY_NODE_DEFINITION_ARRAY);
        } else {
            return null;
        }
    }

    @Override
    public List<? extends NodeDefinitionTemplate> getNodeDefinitionTemplates() {
        if (nodeDefinitionTemplates == null) {
            nodeDefinitionTemplates = Lists.newArrayList();
        }
        return nodeDefinitionTemplates;
    }

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

    public String toString() {
        return String.format("NodeTypeTemplate(%s)", getOakName());
    }

}