/*
 *   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.directory.server.core.api.schema.registries.synchronizers;


import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.naming.NamingException;

import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.Modification;
import org.apache.directory.api.ldap.model.entry.ModificationOperation;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException;
import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.name.Rdn;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.ldap.model.schema.registries.Schema;
import org.apache.directory.api.ldap.schemaloader.SchemaEntityFactory;
import org.apache.directory.api.util.Strings;
import org.apache.directory.server.core.api.entry.ServerEntryUtils;
import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
import org.apache.directory.server.i18n.I18n;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * This class handle modifications made on a global schema. Modifications made
 * on SchemaObjects are handled by the specific shcemaObject synchronizers.
 *
 * @todo poorly implemented - revisit the SchemaChangeHandler for this puppy
 * and do it right.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class SchemaSynchronizer implements RegistrySynchronizer
{
    /** A logger for this class */
    private static final Logger LOG = LoggerFactory.getLogger( SchemaSynchronizer.class );

    private final SchemaEntityFactory factory;

    private final SchemaManager schemaManager;

    /** The global registries */
    //private final Registries registries;

    /** The m-disable AttributeType */
    private final AttributeType disabledAT;

    /** The CN attributeType */
    private final AttributeType cnAT;

    /** The m-dependencies AttributeType */
    private final AttributeType dependenciesAT;

    /** A static Dn referencing ou=schema */
    private final Dn ouSchemaDn;


    /**
     * Creates and initializes a new instance of Schema synchronizer
     *
     * @param schemaManager The server schemaManager
     * @throws Exception If something went wrong
     */
    public SchemaSynchronizer( SchemaManager schemaManager ) throws Exception
    {
        //this.registries = schemaManager.getRegistries();
        this.schemaManager = schemaManager;
        disabledAT = schemaManager.lookupAttributeTypeRegistry( MetaSchemaConstants.M_DISABLED_AT );
        factory = new SchemaEntityFactory();
        cnAT = schemaManager.lookupAttributeTypeRegistry( SchemaConstants.CN_AT );
        dependenciesAT = schemaManager.lookupAttributeTypeRegistry( MetaSchemaConstants.M_DEPENDENCIES_AT );

        ouSchemaDn = new Dn( schemaManager, SchemaConstants.OU_SCHEMA );
    }


    /**
     * The only modification done on a schema element is on the m-disabled
     * attributeType
     *
     * Depending in the existence of this attribute in the previous entry, we will
     * have to update the entry or not.
     */
    public boolean modify( ModifyOperationContext modifyContext, Entry targetEntry, boolean cascade )
        throws LdapException
    {
        Entry entry = modifyContext.getEntry();
        List<Modification> mods = modifyContext.getModItems();
        boolean hasModification = SCHEMA_UNCHANGED;

        // Check if the entry has a m-disabled attribute
        Attribute disabledInEntry = entry.get( disabledAT );
        Modification disabledModification = ServerEntryUtils.getModificationItem( mods, disabledAT );

        // The attribute might be present, but that does not mean we will change it.
        // If it's absent, and if we have it in the previous entry, that mean we want
        // to enable the schema
        if ( disabledModification != null )
        {
            // We are trying to modify the m-disabled attribute.
            ModificationOperation modification = disabledModification.getOperation();
            Attribute attribute = disabledModification.getAttribute();

            hasModification = modifyDisable( modifyContext, modification, attribute, disabledInEntry );
        }
        else if ( disabledInEntry != null )
        {
            hasModification = modifyDisable( modifyContext, ModificationOperation.REMOVE_ATTRIBUTE, null,
                disabledInEntry );
        }

        return hasModification;
    }


    public void moveAndRename( Dn oriChildName, Dn newParentName, Rdn newRn, boolean deleteOldRn, Entry entry,
        boolean cascaded ) throws LdapException
    {

    }


    /**
     * Handles the addition of a metaSchema object to the schema partition.
     *
     * @param name the dn of the new metaSchema object
     * @param entry the attributes of the new metaSchema object
     */
    public void add( Entry entry ) throws LdapException
    {
        Dn dn = entry.getDn();
        Dn parentDn = dn.getParent();

        if ( !parentDn.equals( ouSchemaDn ) )
        {
            throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, I18n.err( I18n.ERR_380,
                ouSchemaDn.getName(),
                parentDn.getNormName() ) );
        }

        // check if the new schema is enabled or disabled
        boolean isEnabled = false;
        Attribute disabled = entry.get( disabledAT );

        if ( disabled == null )
        {
            // If the attribute is absent, then the schema is enabled by default
            isEnabled = true;
        }
        else if ( !disabled.contains( "TRUE" ) )
        {
            isEnabled = true;
        }

        // check to see that all dependencies are resolved and loaded if this
        // schema is enabled, otherwise check that the dependency schemas exist
        checkForDependencies( isEnabled, entry );

        /*
         * There's a slight problem that may result when adding a metaSchema
         * object if the addition of the physical entry fails.  If the schema
         * is enabled when added in the condition tested below, that schema
         * is added to the global registries.  We need to add this so subsequent
         * schema entity additions are loaded into the registries as they are
         * added to the schema partition.  However if the metaSchema object
         * addition fails then we're left with this schema object looking like
         * it is enabled in the registries object's schema hash.  The effects
         * of this are unpredictable.
         *
         * This whole problem is due to the inability of these handlers to
         * react to a failed operation.  To fix this we would need some way
         * for these handlers to respond to failed operations and revert their
         * effects on the registries.
         *
         * TODO: might want to add a set of failedOnXXX methods to the adapter
         * where on failure the schema service calls the schema manager and it
         * calls the appropriate methods on the respective handler.  This way
         * the schema manager can rollback registry changes when LDAP operations
         * fail.
         */

        if ( isEnabled )
        {
            Schema schema = factory.getSchema( entry );
            schemaManager.load( schema );
        }
    }


    /**
     * Called to react to the deletion of a metaSchema object.  This method
     * simply removes the schema from the loaded schema map of the global
     * registries.
     *
     * @param name the dn of the metaSchema object being deleted
     * @param entry the attributes of the metaSchema object
     */
    public void delete( Entry entry, boolean cascade ) throws LdapException
    {
        Attribute cn = entry.get( cnAT );
        String schemaName = cn.getString();

        // Before allowing a schema object to be deleted we must check
        // to make sure it's not depended upon by another schema
        Set<String> dependents = schemaManager.listDependentSchemaNames( schemaName );

        if ( ( dependents != null ) && !dependents.isEmpty() )
        {
            String msg = I18n.err( I18n.ERR_381, dependents );
            LOG.warn( msg );
            throw new LdapUnwillingToPerformException(
                ResultCodeEnum.UNWILLING_TO_PERFORM,
                msg );
        }

        // no need to check if schema is enabled or disabled here
        // if not in the loaded set there will be no negative effect
        schemaManager.unload( schemaName );
    }


    /**
     * Responds to the rdn (commonName) of the metaSchema object being
     * changed.  Changes all the schema entities associated with the
     * renamed schema so they now map to a new schema name.
     *
     * @param name the dn of the metaSchema object renamed
     * @param entry the entry of the metaSchema object before the rename
     * @param newRdn the new commonName of the metaSchema object
     */
    public void rename( Entry entry, Rdn newRdn, boolean cascade ) throws LdapException
    {
        String rdnAttribute = newRdn.getNormType();
        String rdnAttributeOid = schemaManager.getAttributeTypeRegistry().getOidByName( rdnAttribute );

        if ( !rdnAttributeOid.equals( cnAT.getOid() ) )
        {
            throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
                I18n.err( I18n.ERR_382, rdnAttribute ) );
        }

        /*
         * This operation has to do the following:
         *
         * [1] check and make sure there are no dependent schemas on the
         *     one being renamed - if so an exception should result
         *
         * [2] make non-schema object registries modify the mapping
         *     for their entities: non-schema object registries contain
         *     objects that are not SchemaObjects and hence do not carry
         *     their schema within the object as a property
         *
         * [3] make schema object registries do the same but the way
         *     they do them will be different since these objects will
         *     need to be replaced or will require a setter for the
         *     schema name
         */

        // step [1]
        /*
        String schemaName = getSchemaName( entry.getDn() );
        Set<String> dependents = schemaManager.listDependentSchemaNames( schemaName );
        if ( ! dependents.isEmpty() )
        {
            throw new LdapUnwillingToPerformException(
                "Cannot allow a rename on " + schemaName + " schema while it has depentents.",
                ResultCodeEnum.UNWILLING_TO_PERFORM );
        }

        // check if the new schema is enabled or disabled
        boolean isEnabled = false;
        EntryAttribute disabled = entry.get( disabledAT );

        if ( disabled == null )
        {
            isEnabled = true;
        }
        else if ( ! disabled.get().equals( "TRUE" ) )
        {
            isEnabled = true;
        }

        if ( ! isEnabled )
        {
            return;
        }

        // do steps 2 and 3 if the schema has been enabled and is loaded

        // step [2]
        String newSchemaName = ( String ) newRdn.getUpValue();
        registries.getComparatorRegistry().renameSchema( schemaName, newSchemaName );
        registries.getNormalizerRegistry().renameSchema( schemaName, newSchemaName );
        registries.getSyntaxCheckerRegistry().renameSchema( schemaName, newSchemaName );

        // step [3]
        renameSchema( registries.getAttributeTypeRegistry(), schemaName, newSchemaName );
        renameSchema( registries.getDitContentRuleRegistry(), schemaName, newSchemaName );
        renameSchema( registries.getDitStructureRuleRegistry(), schemaName, newSchemaName );
        renameSchema( registries.getMatchingRuleRegistry(), schemaName, newSchemaName );
        renameSchema( registries.getMatchingRuleUseRegistry(), schemaName, newSchemaName );
        renameSchema( registries.getNameFormRegistry(), schemaName, newSchemaName );
        renameSchema( registries.getObjectClassRegistry(), schemaName, newSchemaName );
        renameSchema( registries.getLdapSyntaxRegistry(), schemaName, newSchemaName );
        */
    }


    /**
     * Moves are not allowed for metaSchema objects so this always throws an
     * UNWILLING_TO_PERFORM LdapException.
     */
    public void moveAndRename( Dn oriChildName, Dn newParentName, String newRn, boolean deleteOldRn,
        Entry entry, boolean cascade ) throws LdapUnwillingToPerformException
    {
        throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
            I18n.err( I18n.ERR_383 ) );
    }


    /**
     * Moves are not allowed for metaSchema objects so this always throws an
     * UNWILLING_TO_PERFORM LdapException.
     */
    public void move( Dn oriChildName, Dn newParentName,
        Entry entry, boolean cascade ) throws LdapUnwillingToPerformException
    {
        throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
            I18n.err( I18n.ERR_383 ) );
    }


    // -----------------------------------------------------------------------
    // private utility methods
    // -----------------------------------------------------------------------

    /**
     * Modify the Disable flag (the flag can be set to true or false).
     *
     * We can ADD, REMOVE or MODIFY this flag. The following matrix expose what will be the consequences
     * of this operation, depending on the current state
     *
     * <pre>
     *                 +-------------------+--------------------+--------------------+
     *     op/state    |       TRUE        |       FALSE        |       ABSENT       |
     * +-------+-------+----------------------------------------+--------------------+
     * | ADD   | TRUE  | do nothing        | do nothing         | disable the schema |
     * |       +-------+-------------------+--------------------+--------------------+
     * |       | FALSE | do nothing        | do nothing         | do nothing         |
     * +-------+-------+-------------------+--------------------+--------------------+
     * |REMOVE | N/A   | enable the schema | do nothing         | do nothing         |
     * +-------+-------+-------------------+--------------------+--------------------+
     * |MODIFY | TRUE  | do nothing        | disable the schema | disable the schema |
     * |       +-------+-------------------+--------------------+--------------------+
     * |       | FALSE | enable the schema | do nothing         |  do nothing        |
     * +-------+-------+-------------------+--------------------+--------------------+
     * </pre>
     */
    private boolean modifyDisable( ModifyOperationContext modifyContext, ModificationOperation modOp,
        Attribute disabledInMods, Attribute disabledInEntry ) throws LdapException
    {
        Dn name = modifyContext.getDn();

        switch ( modOp )
        {
        /*
         * If the user is adding a new m-disabled attribute to an enabled schema,
         * we check that the value is "TRUE" and disable that schema if so.
         */
            case ADD_ATTRIBUTE:
                if ( disabledInEntry == null && "TRUE".equalsIgnoreCase( disabledInMods.getString() ) )
                {
                    return disableSchema( getSchemaName( name ) );
                }

                break;

            /*
             * If the user is removing the m-disabled attribute we check if the schema is currently
             * disabled.  If so we enable the schema.
             */
            case REMOVE_ATTRIBUTE:
                if ( ( disabledInEntry != null ) && ( "TRUE".equalsIgnoreCase( disabledInEntry.getString() ) ) )
                {
                    return enableSchema( getSchemaName( name ) );
                }

                break;

            /*
             * If the user is replacing the m-disabled attribute we check if the schema is
             * currently disabled and enable it if the new state has it as enabled.  If the
             * schema is not disabled we disable it if the mods set m-disabled to true.
             */
            case REPLACE_ATTRIBUTE:

                boolean isCurrentlyDisabled = false;

                if ( disabledInEntry != null )
                {
                    isCurrentlyDisabled = "TRUE".equalsIgnoreCase( disabledInEntry.getString() );
                }

                boolean isNewStateDisabled = false;

                if ( disabledInMods != null )
                {
                    Value<?> val = disabledInMods.get();

                    if ( val == null )
                    {
                        isNewStateDisabled = false;
                    }
                    else
                    {
                        isNewStateDisabled = "TRUE".equalsIgnoreCase( val.getString() );
                    }
                }

                if ( isCurrentlyDisabled && !isNewStateDisabled )
                {
                    return enableSchema( getSchemaName( name ) );
                }

                if ( !isCurrentlyDisabled && isNewStateDisabled )
                {
                    return disableSchema( getSchemaName( name ) );
                }

                break;

            default:
                throw new IllegalArgumentException( I18n.err( I18n.ERR_384, modOp ) );
        }

        return SCHEMA_UNCHANGED;
    }


    private String getSchemaName( Dn schema )
    {
        return schema.getRdn().getNormValue().getString();
    }


    private boolean disableSchema( String schemaName ) throws LdapException
    {
        Schema schema = schemaManager.getLoadedSchema( schemaName );

        if ( schema == null )
        {
            // This is not possible. We can't enable a schema which is not loaded.
            String msg = I18n.err( I18n.ERR_85, schemaName );
            LOG.error( msg );
            throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg );
        }

        return schemaManager.disable( schemaName );

    }


    /**
     * Enabling a schema consist on switching all of its schema element to enable.
     * We have to do it on a temporary registries.
     */
    private boolean enableSchema( String schemaName ) throws LdapException
    {
        Schema schema = schemaManager.getLoadedSchema( schemaName );

        if ( schema == null )
        {
            // We have to load the schema before enabling it.
            schemaManager.loadDisabled( schemaName );
        }

        return schemaManager.enable( schemaName );
    }


    /**
     * Checks to make sure the dependencies either exist for disabled metaSchemas,
     * or exist and are loaded (enabled) for enabled metaSchemas.
     *
     * @param isEnabled whether or not the new metaSchema is enabled
     * @param entry the Attributes for the new metaSchema object
     * @throws NamingException if the dependencies do not resolve or are not
     * loaded (enabled)
     */
    private void checkForDependencies( boolean isEnabled, Entry entry ) throws LdapException
    {
        Attribute dependencies = entry.get( this.dependenciesAT );

        if ( dependencies == null )
        {
            return;
        }

        if ( isEnabled )
        {
            // check to make sure all the dependencies are also enabled
            Map<String, Schema> loaded = schemaManager.getRegistries().getLoadedSchemas();

            for ( Value<?> value : dependencies )
            {
                String dependency = value.getString();

                if ( !loaded.containsKey( dependency ) )
                {
                    throw new LdapUnwillingToPerformException(
                        ResultCodeEnum.UNWILLING_TO_PERFORM,
                        "Unwilling to perform operation on enabled schema with disabled or missing dependencies: "
                            + dependency );
                }
            }
        }
        else
        {
            for ( Value<?> value : dependencies )
            {
                String dependency = value.getString();

                if ( schemaManager.getLoadedSchema( Strings.toLowerCase( dependency ) ) == null )
                {
                    throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
                        I18n.err( I18n.ERR_385, dependency ) );
                }
            }
        }
    }
}
