/*
 *   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.component.handler.ipojo;


import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Properties;

import org.apache.directory.server.component.handler.ipojo.property.DirectoryProperty;
import org.apache.directory.server.component.handler.ipojo.property.DirectoryPropertyDescription;
import org.apache.directory.server.hub.api.component.util.ComponentConstants;
import org.apache.felix.ipojo.ConfigurationException;
import org.apache.felix.ipojo.HandlerFactory;
import org.apache.felix.ipojo.PrimitiveHandler;
import org.apache.felix.ipojo.annotations.Handler;
import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.architecture.HandlerDescription;
import org.apache.felix.ipojo.architecture.PropertyDescription;
import org.apache.felix.ipojo.handlers.dependency.Dependency;
import org.apache.felix.ipojo.handlers.dependency.DependencyHandler;
import org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceHandler;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.parser.FieldMetadata;
import org.apache.felix.ipojo.parser.MethodMetadata;
import org.apache.felix.ipojo.parser.PojoMetadata;
import org.apache.felix.ipojo.util.Callback;
import org.apache.felix.ipojo.util.Property;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;


/**
 * Handler Managing ApacheDS configuration.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public abstract class AbstractDcHandler extends PrimitiveHandler
{

    /**
     * List of the configurable fields.
     */
    private List m_configurableProperties = new ArrayList( 1 );

    /**
     * Owning ApacheDS instance of this component.
     */
    private String m_ownerADSInstance;

    /**
     * the handler description.
     */
    private DirectoryComponentHandlerDescription m_description;

    /**
     * Updated method.
     * This method is called when a reconfiguration is completed.
     */
    private Callback m_updated;


    /**
     * Initialize the component type.
     * @param desc : component type description to populate.
     * @param metadata : component type metadata.
     * @throws ConfigurationException : metadata are incorrect.
     */
    public void initializeComponentFactory( ComponentTypeDescription desc, Element metadata )
        throws ConfigurationException
    {
        Element[] confs = metadata.getElements( getHandlerName(), getHandlerNamespaceName() );
        if ( confs == null )
        {
            return;
        }
        Element[] configurables = confs[0].getElements( "DirectoryProperty", getHandlerNamespaceName() );
        for ( int i = 0; configurables != null && i < configurables.length; i++ )
        {
            String fieldName = configurables[i].getAttribute( "field" );
            String methodName = configurables[i].getAttribute( "method" );
            String paramIndex = configurables[i].getAttribute( "constructor-parameter" );

            if ( fieldName == null && methodName == null && paramIndex == null )
            {
                throw new ConfigurationException( "Malformed property : The property needs to contain" +
                    " at least a field, a method or a constructor-parameter" );
            }

            String name = configurables[i].getAttribute( "name" );
            if ( name == null )
            {
                if ( fieldName == null && methodName != null )
                {
                    name = methodName;
                }
                else if ( fieldName == null && paramIndex != null )
                {
                    name = paramIndex;
                }
                else
                {
                    name = fieldName;
                }
                configurables[i].addAttribute( new Attribute( "name", name ) ); // Add the type to avoid configure checking
            }

            // Detect the type of the property
            PojoMetadata manipulation = getFactory().getPojoMetadata();
            String type = null;
            if ( methodName != null )
            {
                MethodMetadata[] method = manipulation.getMethods( methodName );
                if ( method.length == 0 )
                {
                    type = configurables[i].getAttribute( "type" );
                    if ( type == null )
                    {
                        throw new ConfigurationException(
                            "Malformed property : The type of the property cannot be discovered, add a 'type' attribute" );
                    }
                }
                else
                {
                    if ( method[0].getMethodArguments().length != 1 )
                    {
                        throw new ConfigurationException( "Malformed property :  The method " + methodName
                            + " does not have one argument" );
                    }
                    type = method[0].getMethodArguments()[0];
                    configurables[i].addAttribute( new Attribute( "type", type ) ); // Add the type to avoid configure checking
                }
            }
            else if ( fieldName != null )
            {
                FieldMetadata field = manipulation.getField( fieldName );
                if ( field == null )
                {
                    throw new ConfigurationException( "Malformed property : The field " + fieldName
                        + " does not exist in the implementation class" );
                }
                type = field.getFieldType();
                configurables[i].addAttribute( new Attribute( "type", type ) ); // Add the type to avoid configure checking
            }
            else if ( paramIndex != null )
            {
                int index = Integer.parseInt( paramIndex );
                type = configurables[i].getAttribute( "type" );
                MethodMetadata[] cts = manipulation.getConstructors();
                // If we don't have a type, try to get the first constructor and get the type of the parameter
                // we the index 'index'.
                if ( type == null && cts.length > 0 && cts[0].getMethodArguments().length > index )
                {
                    type = cts[0].getMethodArguments()[index];
                }
                else if ( type == null )
                { // Applied only if type was not determined.
                    throw new ConfigurationException( "Cannot determine the type of the property " + index +
                        ", please use the type attribute" );
                }
                configurables[i].addAttribute( new Attribute( "type", type ) );
            }

            boolean mandatory = false;
            String man = configurables[i].getAttribute( "mandatory" );
            mandatory = man != null && man.equalsIgnoreCase( "true" );

            boolean immutable = false;
            String imm = configurables[i].getAttribute( "immutable" );
            immutable = imm != null && imm.equalsIgnoreCase( "true" );

            // If property is constructor index then it must be mandatory.
            if ( paramIndex != null )
            {
                immutable = true;
                mandatory = true;
            }

            String description = configurables[i].getAttribute( "description" );
            String containertype = configurables[i].getAttribute( "containertype" );

            DirectoryPropertyDescription pd = new DirectoryPropertyDescription( name, type, null, description,
                containertype, immutable );

            if ( mandatory )
            {
                pd.setMandatory();
            }

            desc.addProperty( pd );
        }

        desc.addProperty( new DirectoryPropertyDescription( true, ComponentConstants.DC_NATURE_INDICATOR, "true" ) );

        Hashtable<String, String> constantProperties = extractConstantProperties( metadata );
        if ( constantProperties != null )
        {
            for ( String key : constantProperties.keySet() )
            {
                DirectoryPropertyDescription pd = new DirectoryPropertyDescription( true, key,
                    constantProperties.get( key ) );

                desc.addProperty( pd );
            }
        }
    }


    /**
     * Configures the handler.
     * Access to field does not require synchronization as this method is executed
     * before any thread access to this object.
     * @param metadata the metadata of the component
     * @param configuration the instance configuration
     * @throws ConfigurationException one property metadata is not correct
     */
    public void configure( Element metadata, Dictionary configuration ) throws ConfigurationException
    {
        // Owning ApacheDS instance
        String ownerADS = ( String ) configuration.get( DcHandlerConstants.DSCOMPONENT_OWNER_PROP_NAME );
        m_ownerADSInstance = ownerADS;

        // Build the map
        Element[] confs = metadata.getElements( getHandlerName(), getHandlerNamespaceName() );
        Element[] configurables = confs[0].getElements( "DirectoryProperty", getHandlerNamespaceName() );

        // updated method
        String upd = confs[0].getAttribute( "DirectoryUpdated", getHandlerNamespaceName() );
        if ( upd != null )
        {
            MethodMetadata method = getPojoMetadata().getMethod( upd );
            if ( method == null )
            {
                throw new ConfigurationException( "The updated method is not found in the class "
                    + getInstanceManager().getClassName() );
            }
            else if ( method.getMethodArguments().length == 0 )
            {
                m_updated = new Callback( upd, new Class[0], false, getInstanceManager() );
            }
            else if ( method.getMethodArguments().length == 1
                && method.getMethodArguments()[0].equals( Dictionary.class.getName() ) )
            {
                m_updated = new Callback( upd, new Class[]
                    { Dictionary.class }, false, getInstanceManager() );
            }
            else
            {
                throw new ConfigurationException( "The updated method is found in the class "
                    + getInstanceManager().getClassName() + " must have either no argument or a Dictionary" );
            }
        }

        for ( int i = 0; configurables != null && i < configurables.length; i++ )
        {
            String fieldName = configurables[i].getAttribute( "field" );
            String methodName = configurables[i].getAttribute( "method" );
            String paramIndex = configurables[i].getAttribute( "constructor-parameter" );
            int index = -1;

            String name = configurables[i].getAttribute( "name" ); // The initialize method has fixed the property name.
            String type = configurables[i].getAttribute( "type" ); // The initialize method has fixed the property name.
            String desc = configurables[i].getAttribute( "description" );
            String container = configurables[i].getAttribute( "containertype" );

            DirectoryProperty prop = null;
            if ( paramIndex != null )
            {
                index = Integer.parseInt( paramIndex );
            }
            prop = new DirectoryProperty( name, fieldName, methodName, index,
                null, type, desc, container, getInstanceManager(), this );

            addProperty( prop );

            // Check if the instance configuration contains value for the current property :
            if ( configuration.get( name ) != null )
            {
                prop.setValue( configuration.get( name ) );
            }
            else
            {
                if ( fieldName != null && configuration.get( fieldName ) != null )
                {
                    prop.setValue( configuration.get( fieldName ) );
                }
            }

            if ( fieldName != null )
            {
                FieldMetadata field = new FieldMetadata( fieldName, type );
                getInstanceManager().register( field, prop );
            }

            if ( index != -1 )
            {
                getInstanceManager().register( index, prop );
            }
        }

        m_description = new DirectoryComponentHandlerDescription( this, m_configurableProperties );

    }


    /**
      * Stop method.
      * This method is synchronized to avoid the configuration admin pushing a configuration during the un-registration.
      * Do nothing.
      * @see org.apache.felix.ipojo.Handler#stop()
      */
    public synchronized void stop()
    {

    }


    /**
     * Start method.
     */
    public synchronized void start()
    {
        /*
         * Here we provide way to provide one ApacheDS's instances from anothers in same OSGI container.
         * If some ApacheDS component is requiring some other ApacheDS component by @Dependency system, it is ensured
         * to get the component which is instantiated under its own ApacheDS instance.
         */
        if ( m_ownerADSInstance != null )
        {
            // Get the provided service handler :
            ProvidedServiceHandler m_providedServiceHandler = ( ProvidedServiceHandler ) getHandler( HandlerFactory.IPOJO_NAMESPACE
                + ":provides" );

            // Add owning ApacheDS information to every published service of this component.
            if ( m_ownerADSInstance != null )
            {
                Properties ownerADSProps = new Properties();
                ownerADSProps.put( DcHandlerConstants.DSCOMPONENT_OWNER_PROP_NAME, m_ownerADSInstance );
                m_providedServiceHandler.addProperties( ownerADSProps );
            }

            // Get the dependency handler
            DependencyHandler m_dependencyHandler = ( DependencyHandler ) getHandler( HandlerFactory.IPOJO_NAMESPACE
                + ":requires" );

            // Add owning ApacheDS instance filter into every Dependency for cross-instance safety
            Dependency[] dependencies = m_dependencyHandler.getDependencies();
            for ( Dependency dep : dependencies )
            {
                String currentFilter = dep.getFilter();

                String ownerProp = DcHandlerConstants.DSCOMPONENT_OWNER_PROP_NAME;
                String owningRestriction = "(|(!(" + ownerProp + "=*))(" + ownerProp + "=" + m_ownerADSInstance + "))";

                String augmentedFilter = "(&" + currentFilter + owningRestriction + ")";

                try
                {
                    Filter filter = getInstanceManager().getContext().createFilter( augmentedFilter );
                    dep.setFilter( filter );
                }
                catch ( InvalidSyntaxException e )
                {
                    info( "Augmented requirement filter is invalid : " + augmentedFilter
                        + " - " + e.getMessage() );
                }

            }
        }

        // Give initial values and reset the 'invoked' flag.
        for ( int i = 0; i < m_configurableProperties.size(); i++ )
        {
            DirectoryProperty prop = ( DirectoryProperty ) m_configurableProperties.get( i );
            prop.reset(); // Clear the invoked flag.
            if ( prop.hasField() && prop.getValue() != Property.NO_VALUE && prop.getValue() != null )
            {
                getInstanceManager().onSet( null, prop.getField(), prop.getValue() );
            }
        }
    }


    /**
     * Adds the given property metadata to the property metadata list.
     *
     * @param prop : property metadata to add
     */
    protected void addProperty( DirectoryProperty prop )
    {
        m_configurableProperties.add( prop );
    }


    /**
     * Checks if the list contains the property.
     *
     * @param name : name of the property
     * @return true if the property exist in the list
     */
    protected boolean containsProperty( String name )
    {
        for ( int i = 0; i < m_configurableProperties.size(); i++ )
        {
            if ( ( ( DirectoryProperty ) m_configurableProperties.get( i ) ).getName().equals( name ) )
            {
                return true;
            }
        }
        return false;
    }


    /**
     * Reconfigure the component instance.
     * Check if the new configuration modifies the current configuration.
     * Invokes the updated method is needed.
     * @param configuration : the new configuration
     */
    public synchronized void reconfigure( Dictionary configuration )
    {
        info( getInstanceManager().getInstanceName() + " is reconfiguring the properties : " + configuration );
        reconfigureProperties( configuration );

        if ( getInstanceManager().getPojoObjects() != null )
        {
            try
            {
                notifyUpdated( null );
            }
            catch ( Throwable e )
            {
                error( "Cannot call the updated method : " + e.getMessage(), e );
            }
        }
    }


    /**
     * Reconfigured configuration properties and returns non matching properties.
     * When called, it must hold the monitor lock.
     * @param configuration : new configuration
     * @return the properties that does not match with configuration properties
     */
    private Properties reconfigureProperties( Dictionary configuration )
    {
        Properties nonmatchingProps = new Properties();
        Enumeration keysEnumeration = configuration.keys();
        while ( keysEnumeration.hasMoreElements() )
        {
            String name = ( String ) keysEnumeration.nextElement();
            Object value = configuration.get( name );
            boolean found = false;
            // Check if the name is a configurable property
            for ( int i = 0; i < m_configurableProperties.size(); i++ )
            {
                DirectoryProperty prop = ( DirectoryProperty ) m_configurableProperties.get( i );
                if ( prop.getName().equals( name ) )
                {
                    reconfigureProperty( prop, value );
                    found = true;
                    break; // Exit the search loop
                }
            }
            if ( !found )
            {
                // The property is not a configurable property, add it to the toPropagate list.
                nonmatchingProps.put( name, value );
            }
        }

        // Every removed configurable property gets reset to its default value
        for ( int i = 0; i < m_configurableProperties.size(); i++ )
        {
            DirectoryProperty prop = ( DirectoryProperty ) m_configurableProperties.get( i );
            if ( configuration.get( prop.getName() ) == null )
            {
                reconfigureProperty( prop, prop.getDefaultValue() );
            }
        }

        // Complex typed property change notification detection, and setter execution
        String innerReconfTarget = ( String ) configuration.get( "ads-inner-reconfiguration" );
        if ( innerReconfTarget != null )
        {
            for ( int i = 0; i < m_configurableProperties.size(); i++ )
            {
                DirectoryProperty prop = ( DirectoryProperty ) m_configurableProperties.get( i );
                if ( prop.getName().equals( innerReconfTarget ) )
                {
                    if ( prop.getValue().equals( configuration.get( innerReconfTarget ) ) )
                    {
                        /*
                         * Then above code didn't called property method.
                         * If it has method, we want it to be called.
                         */
                        if ( prop.hasMethod() )
                        {
                            if ( getInstanceManager().getPojoObjects() != null )
                            {
                                prop.reset();
                                prop.invoke( getInstanceManager().getPojoObject() );
                            }
                        }
                    }
                }
            }
        }
        return nonmatchingProps;

    }


    /**
     * Reconfigures the given property with the given value.
     * This methods handles {@link org.apache.felix.ipojo.InstanceManager#onSet(Object, String, Object)}
     * call and the callback invocation.
     * The reconfiguration occurs only if the value changes.
     * @param prop the property object to reconfigure
     * @param value the new value.
     */
    public void reconfigureProperty( DirectoryProperty prop, Object value )
    {
        if ( prop.getValue() == null || !prop.getValue().equals( value ) )
        {
            prop.setValue( value );
            if ( prop.hasField() )
            {
                getInstanceManager().onSet( null, prop.getField(), prop.getValue() ); // Notify other handler of the field value change.
            }
            if ( prop.hasMethod() )
            {
                if ( getInstanceManager().getPojoObjects() != null )
                {
                    prop.invoke( null ); // Call on all created pojo objects.
                }
            }
        }
    }


    /**
     * Handler createInstance method.
     * This method is override to allow delayed callback invocation.
     * Invokes the updated method is needed.
     * @param instance : the created object
     */
    public void onCreation( Object instance )
    {
        for ( int i = 0; i < m_configurableProperties.size(); i++ )
        {
            DirectoryProperty prop = ( DirectoryProperty ) m_configurableProperties.get( i );
            if ( prop.hasMethod() )
            {
                prop.invoke( instance );
            }
        }

        try
        {
            notifyUpdated( instance );
        }
        catch ( Throwable e )
        {
            error( "Cannot call the updated method : " + e.getMessage(), e );
        }
    }


    /**
     * Invokes the updated method.
     * This method build the dictionary containing all valued properties,
     * as well as properties propagated to the provided service handler (
     * only if the propagation is enabled).
     * @param instance the instance on which the callback must be called.
     * If <code>null</code> the callback is called on all the existing
     * object.
     */
    private void notifyUpdated( Object instance )
    {
        if ( m_updated == null )
        {
            return;
        }

        if ( m_updated.getArguments().length == 0 )
        {
            // We don't have to compute the properties,
            // we just call the callback.
            try
            {
                if ( instance == null )
                {
                    m_updated.call( new Object[0] );
                }
                else
                {
                    m_updated.call( instance, new Object[0] );
                }
            }
            catch ( Exception e )
            {
                error( "Cannot call the updated method " + m_updated.getMethod() + " : " + e.getMessage() );
            }
            return;
        }

        // Else we must compute the properties.
        Properties props = new Properties();
        for ( int i = 0; i < m_configurableProperties.size(); i++ )
        {
            String n = ( ( Property ) m_configurableProperties.get( i ) ).getName();
            Object v = ( ( Property ) m_configurableProperties.get( i ) ).getValue();
            if ( v != Property.NO_VALUE )
            {
                props.put( n, v );
            }
        }

        try
        {
            if ( instance == null )
            {
                m_updated.call( new Object[]
                    { props } );
            }
            else
            {
                m_updated.call( instance, new Object[]
                    { props } );
            }
        }
        catch ( Exception e )
        {
            error( "Cannot call the updated method " + m_updated.getMethod() + " : " + e.getMessage() );
        }
    }


    /**
     * Gets the directory component handler description.
     * @return the directory component handler description.
     */
    public HandlerDescription getDescription()
    {
        return m_description;
    }


    protected abstract String getHandlerName();


    protected abstract String getHandlerNamespaceName();


    protected abstract Hashtable<String, String> extractConstantProperties( Element ipojoMetadata );
}
