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


import org.apache.directory.server.constants.ApacheSchemaConstants;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.interceptor.BaseInterceptor;
import org.apache.directory.server.core.interceptor.NextInterceptor;
import org.apache.directory.server.core.interceptor.context.AddOperationContext;
import org.apache.directory.server.core.interceptor.context.DeleteOperationContext;
import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
import org.apache.directory.server.core.invocation.Invocation;
import org.apache.directory.server.core.invocation.InvocationStack;
import org.apache.directory.server.core.partition.PartitionNexusProxy;
import org.apache.directory.server.core.schema.SchemaService;
import org.apache.directory.shared.ldap.ldif.ChangeType;
import org.apache.directory.shared.ldap.ldif.Entry;
import org.apache.directory.shared.ldap.ldif.LdifUtils;
import org.apache.directory.shared.ldap.message.ModificationItemImpl;
import org.apache.directory.shared.ldap.name.LdapDN;
import org.apache.directory.shared.ldap.name.Rdn;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.util.AttributeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;


/**
 * An interceptor which intercepts write operations to the directory and
 * logs them with the server's ChangeLog service.
 */
public class ChangeLogInterceptor extends BaseInterceptor
{
    /** for debugging */
    private static final Logger LOG = LoggerFactory.getLogger( ChangeLogInterceptor.class );
    /** used to ignore modify operations to tombstone entries */
    private AttributeType entryDeleted;
    /** the changelog service to log changes to */
    private ChangeLog changeLog;
    /** we need the schema service to deal with special conditions */
    private SchemaService schemaService;

    // -----------------------------------------------------------------------
    // Overridden init() and destroy() methods
    // -----------------------------------------------------------------------


    public void init( DirectoryService directoryService ) throws NamingException
    {
        super.init( directoryService );

        changeLog = directoryService.getChangeLog();
        schemaService = directoryService.getSchemaService();
        entryDeleted = directoryService.getRegistries().getAttributeTypeRegistry()
                .lookup( ApacheSchemaConstants.ENTRY_DELETED_OID );
    }


    // -----------------------------------------------------------------------
    // Overridden (only change inducing) intercepted methods
    // -----------------------------------------------------------------------

    public void add( NextInterceptor next, AddOperationContext opContext ) throws NamingException
    {
        next.add( opContext );

        if ( ! changeLog.isEnabled() || opContext.isCollateralOperation() )
        {
            return;
        }

        Entry forward = new Entry();
        forward.setChangeType( ChangeType.Add );
        forward.setDn( opContext.getDn().getUpName() );
        NamingEnumeration<? extends Attribute> list = opContext.getEntry().getAll();
        
        while ( list.hasMore() )
        {
            forward.addAttribute( ( Attribute ) list.next() );
        }
        
        Entry reverse = LdifUtils.reverseAdd( opContext.getDn() );
        changeLog.log( getPrincipal(), forward, reverse );
    }


    /**
     * The delete operation has to be stored with a way to restore the deleted element.
     * There is no way to do that but reading the entry and dump it into the LOG.
     */
    public void delete( NextInterceptor next, DeleteOperationContext opContext ) throws NamingException
    {
        // @todo make sure we're not putting in operational attributes that cannot be user modified
        // must save the entry if change log is enabled
        Attributes attributes = null;

        if ( changeLog.isEnabled() && ! opContext.isCollateralOperation() )
        {
            attributes = getAttributes( opContext.getDn() );
        }

        next.delete( opContext );

        if ( ! changeLog.isEnabled() || opContext.isCollateralOperation() )
        {
            return;
        }

        Entry forward = new Entry();
        forward.setChangeType( ChangeType.Delete );
        forward.setDn( opContext.getDn().getUpName() );
        Entry reverse = LdifUtils.reverseDel( opContext.getDn(), attributes );
        changeLog.log( getPrincipal(), forward, reverse );
    }


    /**
     * Gets attributes required for modifications.
     *
     * @param dn the dn of the entry to get
     * @return the entry's attributes (may be immutable if the schema subentry)
     * @throws NamingException on error accessing the entry's attributes
     */
    private Attributes getAttributes( LdapDN dn ) throws NamingException
    {
        Attributes attributes;

        // @todo make sure we're not putting in operational attributes that cannot be user modified
        Invocation invocation = InvocationStack.getInstance().peek();
        PartitionNexusProxy proxy = invocation.getProxy();

        if ( schemaService.isSchemaSubentry( dn.toNormName() ) )
        {
            return schemaService.getSubschemaEntryCloned();
        }
        else
        {
            attributes = proxy.lookup( new LookupOperationContext( dn ), PartitionNexusProxy.LOOKUP_BYPASS );
        }

        return attributes;
    }


    public void modify( NextInterceptor next, ModifyOperationContext opContext ) throws NamingException
    {
        Attributes attributes = null;
        boolean isDelete = AttributeUtils.getAttribute( opContext.getModItems(), entryDeleted ) != null;

        if ( ! isDelete && ( changeLog.isEnabled() && ! opContext.isCollateralOperation() ) )
        {
            // @todo make sure we're not putting in operational attributes that cannot be user modified
            attributes = getAttributes( opContext.getDn() );
        }

        next.modify( opContext );

        // @TODO: needs big consideration!!!
        // NOTE: perhaps we need to log this as a system operation that cannot and should not be reapplied?
        if ( isDelete || ! changeLog.isEnabled() || opContext.isCollateralOperation() )
        {
            if ( isDelete )
            {
                LOG.debug( "Bypassing changelog on modify of entryDeleted attribute." );
            }
            return;
        }

        Entry forward = new Entry();
        forward.setChangeType( ChangeType.Modify );
        forward.setDn( opContext.getDn().getUpName() );
        for ( ModificationItemImpl modItem : opContext.getModItems() )
        {
            forward.addModificationItem( modItem );
        }

        Entry reverse = LdifUtils.reverseModify( opContext.getDn(), opContext.getModItems(), attributes );
        changeLog.log( getPrincipal(), forward, reverse );
    }


    // -----------------------------------------------------------------------
    // Though part left as an exercise (Not Any More!)
    // -----------------------------------------------------------------------


    public void rename ( NextInterceptor next, RenameOperationContext renameContext ) throws NamingException
    {
        Attributes attributes = null;
        if ( changeLog.isEnabled() && ! renameContext.isCollateralOperation() )
        {
            // @todo make sure we're not putting in operational attributes that cannot be user modified
            attributes = getAttributes( renameContext.getDn() );
        }

        next.rename( renameContext );

        if ( ! changeLog.isEnabled() || renameContext.isCollateralOperation() )
        {
            return;
        }

        Entry forward = new Entry();
        forward.setChangeType( ChangeType.ModRdn );
        forward.setDn( renameContext.getDn().getUpName() );
        forward.setDeleteOldRdn( renameContext.getDelOldDn() );

        Entry reverse = LdifUtils.reverseModifyRdn( attributes, null, renameContext.getDn(),
                new Rdn( renameContext.getNewRdn() ) );
        changeLog.log( getPrincipal(), forward, reverse );
    }


    public void moveAndRename( NextInterceptor next, MoveAndRenameOperationContext opCtx )
        throws NamingException
    {
        Attributes attributes = null;
        if ( changeLog.isEnabled() && ! opCtx.isCollateralOperation() )
        {
            // @todo make sure we're not putting in operational attributes that cannot be user modified
            Invocation invocation = InvocationStack.getInstance().peek();
            PartitionNexusProxy proxy = invocation.getProxy();
            attributes = proxy.lookup( new LookupOperationContext( opCtx.getDn() ),
                    PartitionNexusProxy.LOOKUP_BYPASS );
        }

        next.moveAndRename( opCtx );

        if ( ! changeLog.isEnabled() || opCtx.isCollateralOperation() )
        {
            return;
        }

        Entry forward = new Entry();
        forward.setChangeType( ChangeType.ModDn );
        forward.setDn( opCtx.getDn().getUpName() );
        forward.setDeleteOldRdn( opCtx.getDelOldDn() );
        forward.setNewRdn( opCtx.getNewRdn().getUpName() );
        forward.setNewSuperior( opCtx.getParent().getUpName() );

        Entry reverse = LdifUtils.reverseModifyRdn( attributes, opCtx.getParent(), opCtx.getDn(),
                new Rdn( opCtx.getNewRdn() ) );
        changeLog.log( getPrincipal(), forward, reverse );
    }


    public void move ( NextInterceptor next, MoveOperationContext opCtx ) throws NamingException
    {
        next.move( opCtx );

        if ( ! changeLog.isEnabled() || opCtx.isCollateralOperation() )
        {
            return;
        }

        Entry forward = new Entry();
        forward.setChangeType( ChangeType.ModDn );
        forward.setDn( opCtx.getDn().getUpName() );
        forward.setNewSuperior( opCtx.getParent().getUpName() );

        Entry reverse = LdifUtils.reverseModifyDn( opCtx.getParent(), opCtx.getDn() );
        changeLog.log( getPrincipal(), forward, reverse );
    }
}