/*
 * 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.chemistry.opencmis.inmemory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractPropertyDefinition;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.TypeDefinitionContainerImpl;
import org.apache.chemistry.opencmis.inmemory.types.DocumentTypeCreationHelper;
import org.apache.chemistry.opencmis.inmemory.types.TypeUtil;
import org.apache.chemistry.opencmis.server.support.TypeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class that manages a type system for a repository types can be added, the
 * inheritance can be managed and type can be retrieved for a given type id.
 */
public class TypeManagerImpl implements TypeManager {

    private static final Logger LOG = LoggerFactory.getLogger(TypeManagerImpl.class.getName());
    /**
     * map from repository id to a types map.
     */
    private final Map<String, TypeDefinitionContainer> fTypesMap = new HashMap<String, TypeDefinitionContainer>();

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.chemistry.opencmis.inmemory.TypeManager#getTypeById(java.lang
     * .String)
     */
    @Override
    public TypeDefinitionContainer getTypeById(String typeId) {
        return fTypesMap.get(typeId);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.chemistry.opencmis.inmemory.TypeManager#getTypeByQueryName
     * (java.lang.String)
     */
    @Override
    public TypeDefinition getTypeByQueryName(String typeQueryName) {
        for (Entry<String, TypeDefinitionContainer> entry : fTypesMap.entrySet()) {
            if (entry.getValue().getTypeDefinition().getQueryName().equals(typeQueryName)) {
                return entry.getValue().getTypeDefinition();
            }
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.chemistry.opencmis.inmemory.TypeManager#getTypeDefinitionList
     * ()
     */
    @Override
    public Collection<TypeDefinitionContainer> getTypeDefinitionList() {
        return Collections.unmodifiableCollection(fTypesMap.values());
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.chemistry.opencmis.inmemory.TypeManager#getRootTypes()
     */
    @Override
    public List<TypeDefinitionContainer> getRootTypes() {
        // just take first repository
        List<TypeDefinitionContainer> rootTypes = new ArrayList<TypeDefinitionContainer>();

        for (TypeDefinitionContainer type : fTypesMap.values()) {
            if (isRootType(type)) {
                rootTypes.add(type);
            }
        }

        return rootTypes;
    }

    /**
     * Initialize the type system with the given types. This list must not
     * contain the CMIS default types. The default type are always contained by
     * default.
     * 
     * @param typesList
     *            list of types to add to the repository
     * 
     * @param createCmisDefaultTypes
     *            indicates if CMIS base types should be added to list
     */
    public void initTypeSystem(List<TypeDefinition> typesList, boolean createCmisDefaultTypes) {

        if (createCmisDefaultTypes) {
            createCmisDefaultTypes();
        }

        // merge all types from the list and build the correct hierachy with
        // children and property lists
        if (null != typesList) {
            for (TypeDefinition typeDef : typesList) {
                addTypeDefinition(typeDef, true);
            }
        }

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.chemistry.opencmis.inmemory.storedobj.api.TypeManagerCreatable
     * #addTypeDefinition(org.apache.chemistry.opencmis.commons.definitions.
     * TypeDefinition, boolean)
     */
    @Override
    public void addTypeDefinition(TypeDefinition cmisType, boolean addInheritedProperties) {

        LOG.info("Adding type definition with name " + cmisType.getLocalName() + " and id " + cmisType.getId()
                + " to repository.");
        TypeDefinitionContainerImpl typeContainer = new TypeDefinitionContainerImpl(cmisType);

        if (null != cmisType.getParentTypeId()) {
            // add new type to children of parent types
            TypeDefinitionContainer parentTypeContainer = fTypesMap.get(cmisType.getParentTypeId());
            parentTypeContainer.getChildren().add(typeContainer);

            if (addInheritedProperties) {
                // recursively add inherited properties
                Map<String, PropertyDefinition<?>> propDefs = typeContainer.getTypeDefinition()
                        .getPropertyDefinitions();
                addInheritedProperties(propDefs, parentTypeContainer.getTypeDefinition());
            }
        }
        // add type to type map
        fTypesMap.put(cmisType.getId(), typeContainer);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.chemistry.opencmis.inmemory.storedobj.api.TypeManagerCreatable
     * #updateTypeDefinition(org.apache.chemistry.opencmis.commons.definitions.
     * TypeDefinition)
     */
    @Override
    public void updateTypeDefinition(TypeDefinition typeDefinition) {
        throw new CmisNotSupportedException("updating a type definition is not supported.");
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.chemistry.opencmis.inmemory.storedobj.api.TypeManagerCreatable
     * #deleteTypeDefinition(java.lang.String)
     */
    @Override
    public void deleteTypeDefinition(String typeId) {
        TypeDefinitionContainer typeDef = fTypesMap.remove(typeId);
        // remove type from children of parent types
        TypeDefinitionContainer parentTypeContainer = fTypesMap.get(typeDef.getTypeDefinition().getParentTypeId());
        parentTypeContainer.getChildren().remove(typeDef);
        fTypesMap.remove(typeId);
    }

    /**
     * Remove all types from the type system. After this call only the default
     * CMIS types are present in the type system. Use this method with care, its
     * mainly intended for unit tests
     * 
     * @param repositoryId
     */
    public void clearTypeSystem() {
        fTypesMap.clear();
        createCmisDefaultTypes();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.chemistry.opencmis.inmemory.TypeManager#getPropertyIdForQueryName
     * (org.apache.chemistry.opencmis.commons.definitions.TypeDefinition,
     * java.lang.String)
     */
    @Override
    public String getPropertyIdForQueryName(TypeDefinition typeDefinition, String propQueryName) {
        for (PropertyDefinition<?> pd : typeDefinition.getPropertyDefinitions().values()) {
            if (pd.getQueryName().equals(propQueryName)) {
                return pd.getId();
            }
        }
        return null;
    }

    private void addInheritedProperties(Map<String, PropertyDefinition<?>> propDefs, TypeDefinition typeDefinition) {

        if (null == typeDefinition) {
            return;
        }

        if (null != typeDefinition.getPropertyDefinitions()) {
            addInheritedPropertyDefinitions(propDefs, typeDefinition.getPropertyDefinitions());
        }

        TypeDefinitionContainer parentTypeContainer = fTypesMap.get(typeDefinition.getParentTypeId());
        TypeDefinition parentType = (null == parentTypeContainer ? null : parentTypeContainer.getTypeDefinition());
        addInheritedProperties(propDefs, parentType);
    }

    private static void addInheritedPropertyDefinitions(Map<String, PropertyDefinition<?>> propDefs,
            Map<String, PropertyDefinition<?>> superPropDefs) {

        for (Entry<String, PropertyDefinition<?>> superProp : superPropDefs.entrySet()) {
            PropertyDefinition<?> superPropDef = superProp.getValue();
            PropertyDefinition<?> clone = clonePropertyDefinition(superPropDef);
            ((AbstractPropertyDefinition<?>) clone).setIsInherited(true);
            propDefs.put(superProp.getKey(), clone);
        }
    }

    private void createCmisDefaultTypes() {
        List<TypeDefinition> typesList = DocumentTypeCreationHelper.createDefaultTypes();
        for (TypeDefinition typeDef : typesList) {
            TypeDefinitionContainerImpl typeContainer = new TypeDefinitionContainerImpl(typeDef);
            fTypesMap.put(typeDef.getId(), typeContainer);
        }
    }

    private static boolean isRootType(TypeDefinitionContainer c) {
        return (c.getTypeDefinition().getId().equals(c.getTypeDefinition().getBaseTypeId().value()));
    }

    private static PropertyDefinition<?> clonePropertyDefinition(PropertyDefinition<?> src) {
        PropertyDefinition<?> clone = TypeUtil.clonePropertyDefinition(src);
        return clone;
    }

}
