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


import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.cursor.Cursor;
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.StringValue;
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.filter.EqualityNode;
import org.apache.directory.api.ldap.model.message.AliasDerefMode;
import org.apache.directory.api.ldap.model.message.SearchScope;
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.ObjectClass;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.server.config.beans.AdsBaseBean;
import org.apache.directory.server.config.beans.ConfigBean;
import org.apache.directory.server.core.api.interceptor.context.SearchOperationContext;
import org.apache.directory.server.core.partition.impl.btree.AbstractBTreePartition;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.server.xdbm.IndexEntry;
import org.apache.directory.server.xdbm.search.PartitionSearchResult;
import org.apache.directory.server.xdbm.search.SearchEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * A class used for reading the configuration present in a Partition
 * and instantiate the necessary objects like DirectoryService, Interceptors etc.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class ConfigPartitionReader
{
    /** The logger for this class */
    private static final Logger LOG = LoggerFactory.getLogger( ConfigPartitionReader.class );

    /** the partition which holds the configuration data */
    private AbstractBTreePartition configPartition;

    /** the search engine of the partition */
    private SearchEngine se;

    /** the schema manager set in the config partition */
    private SchemaManager schemaManager;

    /** The prefix for all the configuration ObjectClass names */
    private static final String ADS_PREFIX = "ads-";

    /** The suffix for the bean */
    private static final String ADS_SUFFIX = "Bean";


    /**
     * 
     * Creates a new instance of ConfigPartitionReader.
     *
     * @param configPartition the non null config partition
     */
    public ConfigPartitionReader( AbstractBTreePartition configPartition )
    {
        if ( configPartition == null )
        {
            throw new IllegalArgumentException( I18n.err( I18n.ERR_503 ) );
        }

        if ( !configPartition.isInitialized() )
        {
            throw new IllegalStateException( I18n.err( I18n.ERR_504 ) );
        }

        this.configPartition = configPartition;
        se = configPartition.getSearchEngine();
        this.schemaManager = configPartition.getSchemaManager();
    }


    /**
     * Find the upper objectclass in a hierarchy. All the inherited ObjectClasses
     * will be removed.
     */
    private ObjectClass findObjectClass( Attribute objectClass ) throws Exception
    {
        Set<ObjectClass> candidates = new HashSet<ObjectClass>();

        try
        {
            // Create the set of candidates
            for ( Value<?> ocValue : objectClass )
            {
                String ocName = ocValue.getString();
                String ocOid = schemaManager.getObjectClassRegistry().getOidByName( ocName );
                ObjectClass oc = schemaManager.getObjectClassRegistry().get( ocOid );

                if ( oc.isStructural() )
                {
                    candidates.add( oc );
                }
            }
        }
        catch ( Exception e )
        {
            throw e;
        }

        // Now find the parent OC
        for ( Value<?> ocValue : objectClass )
        {
            String ocName = ocValue.getString();
            String ocOid = schemaManager.getObjectClassRegistry().getOidByName( ocName );
            ObjectClass oc = schemaManager.getObjectClassRegistry().get( ocOid );

            for ( ObjectClass superior : oc.getSuperiors() )
            {
                if ( oc.isStructural() )
                {
                    if ( candidates.contains( superior ) )
                    {
                        candidates.remove( superior );
                    }
                }
            }
        }

        // The remaining OC in the candidates set is the one we are looking for
        ObjectClass result = candidates.toArray( new ObjectClass[]
            {} )[0];

        LOG.debug( "The top level object class is {}", result.getName() );
        return result;
    }


    /**
     * Create the base Bean from the ObjectClass name.
     * The bean name is constructed using the OjectClass name, by
     * removing the ADS prefix, upper casing the first letter and adding "Bean" at the end.
     * 
     * For instance, ads-directoryService wil become DirectoryServiceBean
     */
    private AdsBaseBean createBean( ObjectClass objectClass ) throws ConfigurationException
    {
        // The remaining OC in the candidates set is the one we are looking for
        String objectClassName = objectClass.getName();

        // Now, let's instantiate the associated bean. Get rid of the 'ads-' in front of the name,
        // and uppercase the first letter. Finally add "Bean" at the end and add the package.
        //String beanName = this.getClass().getPackage().getName() + "org.apache.directory.server.config.beans." + Character.toUpperCase( objectClassName.charAt( 4 ) ) + objectClassName.substring( 5 ) + "Bean";
        String beanName = this.getClass().getPackage().getName() + ".beans." +
            Character.toUpperCase( objectClassName.charAt( ADS_PREFIX.length() ) ) +
            objectClassName.substring( ADS_PREFIX.length() + 1 ) + ADS_SUFFIX;

        try
        {
            Class<?> clazz = Class.forName( beanName );
            Constructor<?> constructor = clazz.getConstructor();
            AdsBaseBean bean = ( AdsBaseBean ) constructor.newInstance();

            LOG.debug( "Bean {} created for ObjectClass {}", beanName, objectClassName );

            return bean;
        }
        catch ( ClassNotFoundException cnfe )
        {
            String message = "Cannot find a Bean class for the ObjectClass name " + objectClassName;
            LOG.error( message );
            throw new ConfigurationException( message );
        }
        catch ( SecurityException se )
        {
            String message = "Cannot access to the class " + beanName;
            LOG.error( message );
            throw new ConfigurationException( message );
        }
        catch ( NoSuchMethodException nsme )
        {
            String message = "Cannot find a constructor for the class " + beanName;
            LOG.error( message );
            throw new ConfigurationException( message );
        }
        catch ( InvocationTargetException ite )
        {
            String message = "Cannot invoke the class " + beanName + ", " + ite.getMessage();
            LOG.error( message );
            throw new ConfigurationException( message );
        }
        catch ( IllegalAccessException iae )
        {
            String message = "Cannot access to the constructor for class " + beanName;
            LOG.error( message );
            throw new ConfigurationException( message );
        }
        catch ( InstantiationException ie )
        {
            String message = "Cannot instantiate the class " + beanName + ", " + ie.getMessage();
            LOG.error( message );
            throw new ConfigurationException( message );
        }
    }


    /**
     * Read the single entry value for an AttributeType, and feed the Bean field with this value
     */
    private void readSingleValueField( AdsBaseBean bean, Field beanField, Attribute fieldAttr )
        throws ConfigurationException
    {
        if ( fieldAttr == null )
        {
            return;
        }

        Value<?> value = fieldAttr.get();
        String valueStr = value.getString();
        Class<?> type = beanField.getType();

        // Process the value accordingly to its type.
        try
        {
            if ( type == String.class )
            {
                beanField.set( bean, valueStr );
            }
            else if ( type == byte[].class )
            {
                beanField.set( bean, value.getBytes() );
            }
            else if ( type == int.class )
            {
                beanField.setInt( bean, Integer.parseInt( valueStr ) );
            }
            else if ( type == long.class )
            {
                beanField.setLong( bean, Long.parseLong( valueStr ) );
            }
            else if ( type == boolean.class )
            {
                beanField.setBoolean( bean, Boolean.parseBoolean( valueStr ) );
            }
            else if ( type == Dn.class )
            {
                try
                {
                    Dn dn = new Dn( valueStr );
                    beanField.set( bean, dn );
                }
                catch ( LdapInvalidDnException lide )
                {
                    String message = "The Dn '" + valueStr + "' for attribute " + fieldAttr.getId()
                        + " is not a valid Dn";
                    LOG.error( message );
                    throw new ConfigurationException( message );
                }
            }
        }
        catch ( IllegalArgumentException iae )
        {
            String message = "Cannot store '" + valueStr + "' into attribute " + fieldAttr.getId();
            LOG.error( message );
            throw new ConfigurationException( message );
        }
        catch ( IllegalAccessException e )
        {
            String message = "Cannot store '" + valueStr + "' into attribute " + fieldAttr.getId();
            LOG.error( message );
            throw new ConfigurationException( message );
        }
    }


    /**
     * Read the multiple entry value for an AttributeType, and feed the Bean field with this value
     */
    private void readMultiValuedField( AdsBaseBean bean, Field field, Attribute attribute )
        throws ConfigurationException
    {
        if ( attribute == null )
        {
            return;
        }

        Class<?> type = field.getType();

        String fieldName = field.getName();
        String addMethodName = "add" + Character.toUpperCase( fieldName.charAt( 0 ) ) + fieldName.substring( 1 );

        // loop on the values and inject them in the bean
        for ( Value<?> value : attribute )
        {
            String valueStr = value.getString();

            try
            {
                if ( type == String.class )
                {
                    field.set( bean, valueStr );
                }
                else if ( type == int.class )
                {
                    field.setInt( bean, Integer.parseInt( valueStr ) );
                }
                else if ( type == long.class )
                {
                    field.setLong( bean, Long.parseLong( valueStr ) );
                }
                else if ( type == boolean.class )
                {
                    field.setBoolean( bean, Boolean.parseBoolean( valueStr ) );
                }
                else if ( type == Dn.class )
                {
                    try
                    {
                        Dn dn = new Dn( valueStr );
                        field.set( bean, dn );
                    }
                    catch ( LdapInvalidDnException lide )
                    {
                        String message = "The Dn '" + valueStr + "' for attribute " + attribute.getId()
                            + " is not a valid Dn";
                        LOG.error( message );
                        throw new ConfigurationException( message );
                    }
                }
                else if ( type == Set.class )
                {
                    Type genericFieldType = field.getGenericType();
                    Class<?> fieldArgClass = null;

                    if ( genericFieldType instanceof ParameterizedType )
                    {
                        ParameterizedType parameterizedType = ( ParameterizedType ) genericFieldType;
                        Type[] fieldArgTypes = parameterizedType.getActualTypeArguments();

                        for ( Type fieldArgType : fieldArgTypes )
                        {
                            fieldArgClass = ( Class<?> ) fieldArgType;
                        }
                    }

                    Method method = bean.getClass().getMethod( addMethodName,
                        Array.newInstance( fieldArgClass, 0 ).getClass() );

                    method.invoke( bean, new Object[]
                        { new String[]
                            { valueStr } } );
                }
                else if ( type == List.class )
                {
                    Type genericFieldType = field.getGenericType();
                    Class<?> fieldArgClass = null;

                    if ( genericFieldType instanceof ParameterizedType )
                    {
                        ParameterizedType parameterizedType = ( ParameterizedType ) genericFieldType;
                        Type[] fieldArgTypes = parameterizedType.getActualTypeArguments();

                        for ( Type fieldArgType : fieldArgTypes )
                        {
                            fieldArgClass = ( Class<?> ) fieldArgType;
                        }
                    }

                    Method method = bean.getClass().getMethod( addMethodName,
                        Array.newInstance( fieldArgClass, 0 ).getClass() );

                    method.invoke( bean, new Object[]
                        { new String[]
                            { valueStr } } );
                }
            }
            catch ( IllegalArgumentException iae )
            {
                String message = "Cannot store '" + valueStr + "' into attribute " + attribute.getId();
                LOG.error( message );
                throw new ConfigurationException( message );
            }
            catch ( IllegalAccessException e )
            {
                String message = "Cannot store '" + valueStr + "' into attribute " + attribute.getId();
                LOG.error( message );
                throw new ConfigurationException( message );
            }
            catch ( SecurityException se )
            {
                String message = "Cannot access to the class " + bean.getClass().getName();
                LOG.error( message );
                throw new ConfigurationException( message );
            }
            catch ( NoSuchMethodException nsme )
            {
                String message = "Cannot find a method " + addMethodName + " in the class " + bean.getClass().getName();
                LOG.error( message );
                throw new ConfigurationException( message );
            }
            catch ( InvocationTargetException ite )
            {
                String message = "Cannot invoke the class " + bean.getClass().getName() + ", " + ite.getMessage();
                LOG.error( message );
                throw new ConfigurationException( message );
            }
            catch ( NegativeArraySizeException nase )
            {
                // No way that can happen...
            }
        }
    }


    private void readFieldValue( AdsBaseBean bean, Field field, Entry entry, String attributeTypeName, boolean mandatory )
        throws ConfigurationException
    {
        // Get the entry attribute for this attribute type
        Attribute attribute = entry.get( attributeTypeName );

        if ( ( attribute != null ) && ( attribute.size() > 0 ) )
        {
            if ( !isMultiple( field.getType() ) )
            {
                readSingleValueField( bean, field, attribute );
            }
            else
            {
                readMultiValuedField( bean, field, attribute );
            }
        }
        else
        {
            if ( mandatory )
            {
                // the requested element is mandatory so let's throw an exception
                String message = "No value was configured for entry with DN '"
                    + entry.getDn() + "' and attribute type '" + attributeTypeName + "'.";
                LOG.error( message );
                throw new ConfigurationException( message );
            }
        }
    }


    /**
     * Read some configuration element from the DIT using its name
     */
    private List<AdsBaseBean> read( Dn baseDn, String name, SearchScope scope, boolean mandatory )
        throws ConfigurationException
    {
        LOG.debug( "Reading from '{}', objectClass '{}'", baseDn, name );

        // Search for the element starting at some point in the DIT
        // Prepare the search request
        EqualityNode<String> filter = new EqualityNode<String>(
            schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT ), new StringValue( name ) );
        Cursor<IndexEntry<String, String>> cursor = null;

        // Create a container for all the read beans
        List<AdsBaseBean> beansList = new ArrayList<AdsBaseBean>();

        try
        {
            // Do the search
            SearchOperationContext searchContext = new SearchOperationContext( null );
            searchContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
            searchContext.setDn( baseDn );
            searchContext.setFilter( filter );
            searchContext.setScope( scope );
            PartitionSearchResult searchResult = se.computeResult( schemaManager, searchContext );

            cursor = searchResult.getResultSet();

            // First, check if we have some entries to process.
            if ( !cursor.next() )
            {
                if ( mandatory )
                {
                    cursor.close();

                    // the requested element is mandatory so let's throw an exception
                    String message = "No instance was configured under the DN '"
                        + baseDn + "' for the objectClass '" + name + "'.";
                    LOG.error( message );
                    throw new ConfigurationException( message );
                }
                else
                {
                    return null;
                }
            }

            // Loop on all the found elements
            do
            {
                IndexEntry<String, String> forwardEntry = cursor.get();

                // Now, get the entry
                Entry entry = configPartition.fetch( forwardEntry.getId() );
                LOG.debug( "Entry read : {}", entry );

                // Let's instantiate the bean we need. The upper ObjectClass's name
                // will be used to do that
                ObjectClass objectClass = findObjectClass( entry.get( SchemaConstants.OBJECT_CLASS_AT ) );

                // Instantiating the bean
                AdsBaseBean bean = createBean( objectClass );

                // Setting its DN
                bean.setDn( entry.getDn() );

                // Adding the bean to the list
                beansList.add( bean );

                // Getting the class of the bean
                Class<?> beanClass = bean.getClass();

                // A flag to know when we reached the 'AdsBaseBean' class when 
                // looping on the class hierarchy of the bean
                boolean adsBaseBeanClassFound = false;

                // Looping until the 'AdsBaseBean' class has been found
                while ( !adsBaseBeanClassFound )
                {
                    // Checking if we reached the 'AdsBaseBean' class
                    if ( beanClass == AdsBaseBean.class )
                    {
                        adsBaseBeanClassFound = true;
                    }

                    // Looping on all fields of the bean
                    Field[] fields = beanClass.getDeclaredFields();
                    for ( Field field : fields )
                    {
                        // Making the field accessible (we get an exception if we don't do that)
                        field.setAccessible( true );

                        // Getting the class of the field
                        Class<?> fieldClass = field.getType();

                        // Looking for the @ConfigurationElement annotation
                        ConfigurationElement configurationElement = field.getAnnotation( ConfigurationElement.class );
                        if ( configurationElement != null )
                        {
                            // Getting the annotation's values
                            String fieldAttributeType = configurationElement.attributeType();
                            String fieldObjectClass = configurationElement.objectClass();
                            String container = configurationElement.container();
                            boolean isOptional = configurationElement.isOptional();

                            // Checking if we have a value for the attribute type
                            if ( ( fieldAttributeType != null ) && ( !"".equals( fieldAttributeType ) ) )
                            {
                                readFieldValue( bean, field, entry, fieldAttributeType, !isOptional );
                            }
                            // Checking if we have a value for the object class
                            else if ( ( fieldObjectClass != null ) && ( !"".equals( fieldObjectClass ) ) )
                            {
                                // Checking if this is a multi-valued field (which values are stored in a container)
                                if ( isMultiple( fieldClass ) && ( container != null )
                                    && ( !"".equals( container ) ) )
                                {
                                    // Creating the DN of the container
                                    Dn newBase = entry.getDn().add( "ou=" + container );

                                    // Looking for the field values
                                    Collection<AdsBaseBean> fieldValues = read( newBase, fieldObjectClass,
                                        SearchScope.ONELEVEL, !isOptional );

                                    // Setting the values to the field
                                    if ( ( fieldValues != null ) && ( fieldValues.size() > 0 ) )
                                    {
                                        field.set( bean, fieldValues );
                                    }
                                }
                                // This is a single-value field
                                else
                                {
                                    // Looking for the field values
                                    List<AdsBaseBean> fieldValues = read( entry.getDn(), fieldObjectClass,
                                        SearchScope.ONELEVEL, !isOptional );

                                    // Setting the value to the field
                                    if ( ( fieldValues != null ) && ( fieldValues.size() > 0 ) )
                                    {
                                        field.set( bean, fieldValues.get( 0 ) );
                                    }
                                }
                            }
                        }
                    }

                    // Moving to the upper class in the class hierarchy
                    beanClass = beanClass.getSuperclass();
                }
            }
            while ( cursor.next() );
        }
        catch ( ConfigurationException ce )
        {
            throw ce;
        }
        catch ( Exception e )
        {
            String message = "An error occured while reading the configuration DN '"
                + baseDn + "' for the objectClass '" + name + "':\n" + e.getMessage();
            LOG.error( message );
            throw new ConfigurationException( message );
        }
        finally
        {
            if ( cursor != null )
            {
                try
                {
                    cursor.close();
                }
                catch ( Exception e )
                {
                    // So ??? If the cursor can't be close, there is nothing we can do
                    // but rethrow the exception
                    throw new ConfigurationException( e.getMessage(), e.getCause() );
                }
            }
        }

        return beansList;
    }


    /**
     * Indicates the given type is multiple.
     *
     * @param clazz
     *      the class
     * @return
     *      <code>true</code> if the given is multiple,
     *      <code>false</code> if not.
     */
    private boolean isMultiple( Class<?> clazz )
    {
        return Collection.class.isAssignableFrom( clazz );
    }


    /**
     * Read the configuration from the DIT, returning a bean containing all of it.
     * <p>
     * This method implicitly uses <em>"ou=config"</em> as base Dn
     * 
     * @return The Config bean, containing the whole configuration
     * @throws ConfigurationException If we had some issue reading the configuration
     */
    public ConfigBean readConfig() throws LdapException
    {
        // The starting point is the DirectoryService element
        return readConfig( new Dn( new Rdn( SchemaConstants.OU_AT, "config" ) ) );
    }


    /**
     * Read the configuration from the DIT, returning a bean containing all of it.
     * 
     * @param base The base Dn in the DIT where the configuration is stored
     * @return The Config bean, containing the whole configuration
     * @throws ConfigurationException If we had some issue reading the configuration
     */
    public ConfigBean readConfig( String baseDn ) throws LdapException
    {
        // The starting point is the DirectoryService element
        return readConfig( new Dn( baseDn ) );
    }


    /**
     * Read the configuration from the DIT, returning a bean containing all of it.
     * 
     * @param base The base Dn in the DIT where the configuration is stored
     * @return The Config bean, containing the whole configuration
     * @throws ConfigurationException If we had some issue reading the configuration
     */
    public ConfigBean readConfig( Dn baseDn ) throws ConfigurationException
    {
        // The starting point is the DirectoryService element
        return readConfig( baseDn, ConfigSchemaConstants.ADS_DIRECTORY_SERVICE_OC.getValue() );
    }


    /**
     * Read the configuration from the DIT, returning a bean containing all of it.
     * 
     * @param baseDn The base Dn in the DIT where the configuration is stored
     * @param objectClass The element to read from the DIT
     * @return The bean containing the configuration for the required element
     * @throws ConfigurationException
     */
    public ConfigBean readConfig( String baseDn, String objectClass ) throws LdapException
    {
        return readConfig( new Dn( baseDn ), objectClass );
    }


    /**
     * Read the configuration from the DIT, returning a bean containing all of it.
     * 
     * @param baseDn The base Dn in the DIT where the configuration is stored
     * @param objectClass The element to read from the DIT
     * @return The bean containing the configuration for the required element
     * @throws ConfigurationException
     */
    public ConfigBean readConfig( Dn baseDn, String objectClass ) throws ConfigurationException
    {
        LOG.debug( "Reading configuration for the {} element, from {} ", objectClass, baseDn );
        ConfigBean configBean = new ConfigBean();

        if ( baseDn == null )
        {
            baseDn = configPartition.getSuffixDn();
        }

        List<AdsBaseBean> beans = read( baseDn, objectClass, SearchScope.ONELEVEL, true );

        if ( LOG.isDebugEnabled() )
        {
            if ( ( beans == null ) || ( beans.size() == 0 ) )
            {
                LOG.debug( "No {} element to read", objectClass );
            }
            else
            {
                LOG.debug( beans.get( 0 ).toString() );
            }
        }

        configBean.setDirectoryServiceBeans( beans );

        return configBean;
    }
}
