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

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InvalidAttributeIdentifierException;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchResult;

import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
import org.apache.directory.server.schema.registries.Registries;
import org.apache.directory.shared.ldap.constants.SchemaConstants;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.entry.Modification;
import org.apache.directory.shared.ldap.entry.ModificationOperation;
import org.apache.directory.shared.ldap.entry.Value;
import org.apache.directory.shared.ldap.name.LdapDN;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.schema.SchemaUtils;
import org.apache.directory.shared.ldap.util.EmptyEnumeration;
import org.apache.directory.shared.ldap.util.StringTools;

/**
 * A helper class used to manipulate Entries, Attributes and Values.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 * @version $Rev$, $Date$
 */
public class ServerEntryUtils
{
    /**
     * Convert a ServerAttribute into a BasicAttribute. The DN is lost
     * during this conversion, as the Attributes object does not store
     * this element.
     *
     * @return An instance of a AttributesImpl() object
     */
    public static Attribute toBasicAttribute( ServerAttribute entryAttribute )
    {
        AttributeType attributeType = entryAttribute.getAttributeType();
        
        Attribute attribute = new BasicAttribute( attributeType.getName() );
        
        for ( Value<?> value: entryAttribute )
        {
            attribute.add( value.get() );
        }
        
        return attribute;
    }
    
    
    /**
     * Convert a ServerEntry into a BasicAttributes. The DN is lost
     * during this conversion, as the Attributes object does not store
     * this element.
     *
     * @return An instance of a AttributesImpl() object
     */
    public static Attributes toBasicAttributes( ServerEntry entry )
    {
        if ( entry == null )
        {
            return null;
        }
        
        Attributes attributes = new BasicAttributes( true );

        for ( AttributeType attributeType:entry.getAttributeTypes() )
        {
            EntryAttribute attr = entry.get( attributeType );
            
            // Deal with a special case : an entry without any ObjectClass
            if ( attributeType.getOid().equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
            {
                if ( attr.size() == 0 )
                {
                    // We don't have any objectClass, just dismiss this element
                    continue;
                }
            }
            
            attributes.put( toBasicAttribute( (ServerAttribute)attr ) );
        }
        
        return attributes;
    }


    /**
     * Convert a BasicAttribute or a AttributeImpl to a ServerAtribute
     *
     * @param attribute the BasicAttributes or AttributesImpl instance to convert
     * @param attributeType
     * @return An instance of a ServerEntry object
     * 
     * @throws InvalidAttributeIdentifierException If we had an incorrect attribute
     */
    public static ServerAttribute toServerAttribute( Attribute attribute, AttributeType attributeType )
    {
        if ( attribute == null )
        {
            return null;
        }
        
        try 
        {
            ServerAttribute serverAttribute = new DefaultServerAttribute( attributeType );
        
            for ( NamingEnumeration<?> values = attribute.getAll(); values.hasMoreElements(); )
            {
                Object value = values.nextElement();
                
                if ( serverAttribute.isHR() )
                {
                    if ( value instanceof String )
                    {
                        serverAttribute.add( (String)value );
                    }
                    else if ( value instanceof byte[] )
                    {
                        serverAttribute.add( StringTools.utf8ToString( (byte[])value ) );
                    }
                    else
                    {
                        return null;
                    }
                }
                else
                {
                    if ( value instanceof String )
                    {
                        serverAttribute.add( StringTools.getBytesUtf8( (String)value ) );
                    }
                    else if ( value instanceof byte[] )
                    {
                        serverAttribute.add( (byte[])value );
                    }
                    else
                    {
                        return null;
                    }
                }
            }
            
            return serverAttribute;
        }
        catch ( NamingException ne )
        {
            return null;
        }
    }


    /**
     * Convert a BasicAttributes or a AttributesImpl to a ServerEntry
     *
     * @param attributes the BasicAttributes or AttributesImpl instance to convert
     * @param registries The registries, needed ro build a ServerEntry
     * @param dn The DN which is needed by the ServerEntry 
     * @return An instance of a ServerEntry object
     * 
     * @throws InvalidAttributeIdentifierException If we get an invalid attribute
     */
    public static ServerEntry toServerEntry( Attributes attributes, LdapDN dn, Registries registries ) 
            throws InvalidAttributeIdentifierException
    {
        if ( attributes instanceof BasicAttributes )
        {
            try 
            {
                ServerEntry entry = new DefaultServerEntry( registries, dn );
    
                for ( NamingEnumeration<? extends Attribute> attrs = attributes.getAll(); attrs.hasMoreElements(); )
                {
                    Attribute attr = attrs.nextElement();

                    String attributeId = attr.getID();
                    String id = SchemaUtils.stripOptions( attributeId );
                    Set<String> options = SchemaUtils.getOptions( attributeId );
                    // TODO : handle options.
                    AttributeType attributeType = registries.getAttributeTypeRegistry().lookup( id );
                    ServerAttribute serverAttribute = ServerEntryUtils.toServerAttribute( attr, attributeType );
                    
                    if ( serverAttribute != null )
                    {
                        entry.put( serverAttribute );
                    }
                }
                
                return entry;
            }
            catch ( NamingException ne )
            {
                throw new InvalidAttributeIdentifierException( ne.getMessage() );
            }
        }
        else
        {
            return null;
        }
    }


    /**
     * Gets the target entry as it would look after a modification operation 
     * was performed on it.
     * 
     * @param mod the modification
     * @param entry the source entry that is modified
     * @return the resultant entry after the modification has taken place
     * @throws NamingException if there are problems accessing attributes
     */
    public static ServerEntry getTargetEntry( Modification mod, ServerEntry entry, Registries registries ) throws NamingException
    {
        ServerEntry targetEntry = ( ServerEntry ) entry.clone();
        ModificationOperation modOp = mod.getOperation();
        String id = mod.getAttribute().getId();
        AttributeType attributeType = registries.getAttributeTypeRegistry().lookup( id );
        
        switch ( modOp )
        {
            case REPLACE_ATTRIBUTE :
                targetEntry.put( (ServerAttribute)mod.getAttribute() );
                break;
                
            case REMOVE_ATTRIBUTE :
                ServerAttribute toBeRemoved = (ServerAttribute)mod.getAttribute();

                if ( toBeRemoved.size() == 0 )
                {
                    targetEntry.removeAttributes( id );
                }
                else
                {
                    EntryAttribute existing = targetEntry.get( id );

                    if ( existing != null )
                    {
                        for ( Value<?> value:toBeRemoved )
                        {
                            existing.remove( value );
                        }
                    }
                }
                break;
                
            case ADD_ATTRIBUTE :
                ServerAttribute combined = new DefaultServerAttribute( id, attributeType );
                ServerAttribute toBeAdded = (ServerAttribute)mod.getAttribute();
                EntryAttribute existing = entry.get( id );

                if ( existing != null )
                {
                    for ( Value<?> value:existing )
                    {
                        combined.add( value );
                    }
                }

                for ( Value<?> value:toBeAdded )
                {
                    combined.add( value );
                }
                
                targetEntry.put( combined );
                break;
                
            default:
                throw new IllegalStateException( "undefined modification type: " + modOp );
        }

        return targetEntry;
    }


    /**
     * Creates a new attribute which contains the values representing the union
     * of two attributes. If one attribute is null then the resultant attribute
     * returned is a copy of the non-null attribute. If both are null then we
     * cannot determine the attribute ID and an {@link IllegalArgumentException}
     * is raised.
     * 
     * @param attr0 the first attribute
     * @param attr1 the second attribute
     * @return a new attribute with the union of values from both attribute
     *         arguments
     * @throws NamingException if there are problems accessing attribute values
     */
    public static ServerAttribute getUnion( ServerAttribute attr0, ServerAttribute attr1 )
    {
        if ( attr0 == null && attr1 == null )
        {
            throw new IllegalArgumentException( "Cannot figure out attribute ID if both args are null" );
        }
        else if ( attr0 == null )
        {
            return (ServerAttribute)attr1.clone();
        }
        else if ( attr1 == null )
        {
            return (ServerAttribute)attr0.clone();
        }
        else if ( !attr0.getAttributeType().equals( attr1.getAttributeType() ) )
        {
            throw new IllegalArgumentException( "Cannot take union of attributes with different IDs!" );
        }

        ServerAttribute attr = (ServerAttribute)attr0.clone();

        for ( Value<?> value:attr1 )
        {
            attr.add( value );
        }

        return attr;
    }
    
    
    /**
     * Convert a ModificationItem to an instance of a ServerModification object
     *
     * @param modificationImpl the modification instance to convert
     * @param attributeType the associated attributeType
     * @return a instance of a ServerModification object
     */
    private static Modification toServerModification( ModificationItem modificationImpl, AttributeType attributeType ) 
    {
        ModificationOperation operation;
        
        switch ( modificationImpl.getModificationOp() )
        {
            case DirContext.REMOVE_ATTRIBUTE :
                operation = ModificationOperation.REMOVE_ATTRIBUTE;
                break;
                
            case DirContext.REPLACE_ATTRIBUTE :
                operation = ModificationOperation.REPLACE_ATTRIBUTE;
                break;

            case DirContext.ADD_ATTRIBUTE :
            default :
                operation = ModificationOperation.ADD_ATTRIBUTE;
                break;
                
        }
        
        Modification modification = new ServerModification( 
            operation,
            ServerEntryUtils.toServerAttribute( modificationImpl.getAttribute(), attributeType ) ); 
        
        return modification;
        
    }

    
    /**
     * 
     * Convert a list of ModificationItemImpl to a list of 
     *
     * @param modificationImpls
     * @param atRegistry
     * @return
     * @throws NamingException
     */
    public static List<Modification> convertToServerModification( List<ModificationItem> modificationItems, 
        AttributeTypeRegistry atRegistry ) throws NamingException
    {
        if ( modificationItems != null )
        {
            List<Modification> modifications = new ArrayList<Modification>( modificationItems.size() );

            for ( ModificationItem modificationItem: modificationItems )
            {
                AttributeType attributeType = atRegistry.lookup( modificationItem.getAttribute().getID() );
                modifications.add( toServerModification( modificationItem, attributeType ) );
            }
        
            return modifications;
        }
        else
        {
            return null;
        }
    }
    
    
    /**
     * Convert a Modification to an instance of a ServerModification object.
     *
     * @param modificationImpl the modification instance to convert
     * @param attributeType the associated attributeType
     * @return a instance of a ServerModification object
     */
    private static Modification toServerModification( Modification modification, AttributeType attributeType ) 
    {
        if ( modification instanceof ServerModification )
        {
            return modification;
        }
        
        Modification serverModification = new ServerModification( 
            modification.getOperation(),
            new DefaultServerAttribute( attributeType, modification.getAttribute() ) ); 
        
        return serverModification;
        
    }

    
    public static List<Modification> toServerModification( Modification[] modifications, 
        AttributeTypeRegistry atRegistry ) throws NamingException
    {
        if ( modifications != null )
        {
            List<Modification> modificationsList = new ArrayList<Modification>();
    
            for ( Modification modification: modifications )
            {
                String attributeId = modification.getAttribute().getId();
                String id = stripOptions( attributeId );
                modification.getAttribute().setId( id );
                Set<String> options = getOptions( attributeId );

                // -------------------------------------------------------------------
                // DIRSERVER-646 Fix: Replacing an unknown attribute with no values 
                // (deletion) causes an error
                // -------------------------------------------------------------------
                
                // TODO - after removing JNDI we need to make the server handle 
                // this in the codec
                
                if ( ! atRegistry.hasAttributeType( id ) 
                     && modification.getAttribute().size() == 0 
                     && modification.getOperation() == ModificationOperation.REPLACE_ATTRIBUTE )
                {
                    continue;
                }

                // -------------------------------------------------------------------
                // END DIRSERVER-646 Fix
                // -------------------------------------------------------------------
                
                
                // TODO : handle options
                AttributeType attributeType = atRegistry.lookup( id );
                modificationsList.add( toServerModification( modification, attributeType ) );
            }
        
            return modificationsList;
        }
        else
        {
            return null;
        }
    }


    public static List<Modification> toServerModification( ModificationItem[] modifications, 
        AttributeTypeRegistry atRegistry ) throws NamingException
    {
        if ( modifications != null )
        {
            List<Modification> modificationsList = new ArrayList<Modification>();
    
            for ( ModificationItem modification: modifications )
            {
                String attributeId = modification.getAttribute().getID();
                String id = stripOptions( attributeId );
                Set<String> options = getOptions( attributeId );

                // -------------------------------------------------------------------
                // DIRSERVER-646 Fix: Replacing an unknown attribute with no values 
                // (deletion) causes an error
                // -------------------------------------------------------------------
                
                // TODO - after removing JNDI we need to make the server handle 
                // this in the codec
                
                if ( ! atRegistry.hasAttributeType( id ) 
                     && modification.getAttribute().size() == 0 
                     && modification.getModificationOp() == DirContext.REPLACE_ATTRIBUTE )
                {
                    continue;
                }

                // -------------------------------------------------------------------
                // END DIRSERVER-646 Fix
                // -------------------------------------------------------------------
                
                
                // TODO : handle options
                AttributeType attributeType = atRegistry.lookup( id );
                modificationsList.add( toServerModification( (ModificationItem)modification, attributeType ) );
            }
        
            return modificationsList;
        }
        else
        {
            return null;
        }
    }


    /**
     * Utility method to extract a modification item from an array of modifications.
     * 
     * @param mods the array of ModificationItems to extract the Attribute from.
     * @param type the attributeType spec of the Attribute to extract
     * @return the modification item on the attributeType specified
     */
    public static final Modification getModificationItem( List<Modification> mods, AttributeType type )
    {
        for ( Modification modification:mods )
        {
            ServerAttribute attribute = (ServerAttribute)modification.getAttribute();
            
            if ( attribute.getAttributeType() == type )
            {
                return modification;
            }
        }
        
        return null;
    }
    
    
    /**
     * Utility method to extract an attribute from a list of modifications.
     * 
     * @param mods the list of ModificationItems to extract the Attribute from.
     * @param type the attributeType spec of the Attribute to extract
     * @return the extract Attribute or null if no such attribute exists
     */
    public static ServerAttribute getAttribute( List<Modification> mods, AttributeType type )
    {
        Modification mod = getModificationItem( mods, type );
        
        if ( mod != null )
        {
            return (ServerAttribute)mod.getAttribute();
        }
        
        return null;
    }
    
    
    /**
     * Encapsulate a ServerSearchResult enumeration into a SearchResult enumeration
     * @param result The ServerSearchResult enumeration
     * @return A SearchResultEnumeration
     */
    public static NamingEnumeration<SearchResult> toSearchResultEnum( final NamingEnumeration<ServerSearchResult> result )
    {
        if ( result instanceof EmptyEnumeration<?> )
        {
            return new EmptyEnumeration<SearchResult>();
        }
        
        return new NamingEnumeration<SearchResult> ()
        {
            public void close() throws NamingException
            {
                result.close();
            }


            /**
             * @see javax.naming.NamingEnumeration#hasMore()
             */
            public boolean hasMore() throws NamingException
            {
                return result.hasMore();
            }


            /**
             * @see javax.naming.NamingEnumeration#next()
             */
            public SearchResult next() throws NamingException
            {
                ServerSearchResult rec = result.next();
                
                SearchResult searchResult = new SearchResult( 
                        rec.getDn().getUpName(), 
                        rec.getObject(), 
                        toBasicAttributes( rec.getServerEntry() ), 
                        rec.isRelative() );
                
                return searchResult;
            }
            
            
            /**
             * @see java.util.Enumeration#hasMoreElements()
             */
            public boolean hasMoreElements()
            {
                return result.hasMoreElements();
            }


            /**
             * @see java.util.Enumeration#nextElement()
             */
            public SearchResult nextElement()
            {
                try
                {
                    ServerSearchResult rec = result.next();
    
                    SearchResult searchResult = new SearchResult( 
                            rec.getDn().getUpName(), 
                            rec.getObject(), 
                            toBasicAttributes( rec.getServerEntry() ), 
                            rec.isRelative() );
                    
                    return searchResult;
                }
                catch ( NamingException ne )
                {
                    NoSuchElementException nsee = 
                        new NoSuchElementException( "Encountered NamingException on underlying enumeration." );
                    nsee.initCause( ne );
                    throw nsee;
                }
            }
        };
    }
    
    
    /**
     * Remove the options from the attributeType, and returns the ID.
     * 
     * RFC 4512 :
     * attributedescription = attributetype options
     * attributetype = oid
     * options = *( SEMI option )
     * option = 1*keychar
     */
    private static String stripOptions( String attributeId )
    {
        int optionsPos = attributeId.indexOf( ";" ); 
        
        if ( optionsPos != -1 )
        {
            return attributeId.substring( 0, optionsPos );
        }
        else
        {
            return attributeId;
        }
    }
    

    /**
     * Get the options from the attributeType.
     * 
     * For instance, given :
     * jpegphoto;binary;lang=jp
     * 
     * your get back a set containing { "binary", "lang=jp" }
     */
    private static Set<String> getOptions( String attributeId )
    {
        int optionsPos = attributeId.indexOf( ";" ); 

        if ( optionsPos != -1 )
        {
            Set<String> options = new HashSet<String>();
            
            String[] res = attributeId.substring( optionsPos + 1 ).split( ";" );
            
            for ( String option:res )
            {
                if ( !StringTools.isEmpty( option ) )
                {
                    options.add( option );
                }
            }
            
            return options;
        }
        else
        {
            return null;
        }
    }
}
