/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 */
package org.apache.myrmidon.components.executor;

import java.util.HashMap;
import java.util.ArrayList;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.log.Logger;
import org.apache.myrmidon.api.Task;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.aspects.AspectHandler;
import org.apache.myrmidon.components.aspect.AspectManager;

public class AspectAwareExecutor
    extends DefaultExecutor
{
    private final static Parameters       EMPTY_PARAMETERS;
    private final static Configuration[]  EMPTY_ELEMENTS       = new Configuration[ 0 ];

    static
    {
        EMPTY_PARAMETERS = new Parameters();
        EMPTY_PARAMETERS.makeReadOnly();
    }

    private AspectManager        m_aspectManager;

    /**
     * Retrieve relevent services.
     *
     * @param componentManager the ComponentManager
     * @exception ComponentException if an error occurs
     */
    public void compose( final ComponentManager componentManager )
        throws ComponentException
    {
        super.compose( componentManager );

        m_aspectManager = (AspectManager)componentManager.lookup( AspectManager.ROLE );
    }

    public void execute( final Configuration taskModel, final ExecutionFrame frame )
        throws TaskException
    {
        try
        {
            executeTask( taskModel, frame );
        }
        catch( final TaskException te )
        {
            if( false == getAspectManager().error( te ) )
            {
                throw te;
            }
        }
    }

    private void executeTask( Configuration taskModel, final ExecutionFrame frame )
        throws TaskException
    {
        taskModel = getAspectManager().preCreate( taskModel );
        taskModel = prepareAspects( taskModel );

        getLogger().debug( "Pre-Create" );
        final Task task = createTask( taskModel.getName(), frame );
        getAspectManager().postCreate( task );

        getLogger().debug( "Pre-Loggable" );
        final Logger logger = frame.getLogger();
        getAspectManager().preLoggable( logger );
        doLoggable( task, taskModel, logger );

        getLogger().debug( "Contextualizing" );
        doContextualize( task, taskModel, frame.getContext() );

        getLogger().debug( "Composing" );
        doCompose( task, taskModel, frame.getComponentManager() );

        getLogger().debug( "Configuring" );
        getAspectManager().preConfigure( taskModel );
        doConfigure( task, taskModel, frame.getContext() );

        getLogger().debug( "Initializing" );
        doInitialize( task, taskModel );

        getLogger().debug( "Executing" );
        getAspectManager().preExecute();
        doExecute( taskModel, task );

        getLogger().debug( "Disposing" );
        getAspectManager().preDestroy();
        doDispose( task, taskModel );
    }

    protected void doExecute( final Configuration taskModel, final Task task )
        throws TaskException
    {
        task.execute();
    }

    //TODO: Extract and clean taskModel here.
    //Get all parameters from model and provide to appropriate aspect.
    //aspect( final Parameters parameters, final Configuration[] elements )
    private final Configuration prepareAspects( final Configuration taskModel )
        throws TaskException
    {
        final DefaultConfiguration newTaskModel = 
            new DefaultConfiguration( taskModel.getName(), taskModel.getLocation() );
        final HashMap parameterMap = new HashMap();
        final HashMap elementMap = new HashMap();

        processAttributes( taskModel, newTaskModel, parameterMap );
        processElements( taskModel, newTaskModel, elementMap );

        dispatchAspectsSettings( parameterMap, elementMap );
        checkForUnusedSettings( parameterMap, elementMap );

        return newTaskModel;
    }

    private final void dispatchAspectsSettings( final HashMap parameterMap, 
                                                final HashMap elementMap )
        throws TaskException
    {
        final String[] names = getAspectManager().getNames();
        
        for( int i = 0; i < names.length; i++ )
        {
            final ArrayList elementList = (ArrayList)elementMap.remove( names[ i ] );

            Parameters parameters = (Parameters)parameterMap.remove( names[ i ] );
            if( null == parameters ) parameters = EMPTY_PARAMETERS;

            Configuration[] elements = null;
            if( null == elementList ) elements = EMPTY_ELEMENTS;
            else
            {
                elements = (Configuration[])elementList.toArray( EMPTY_ELEMENTS );
            }
            
            dispatch( names[ i ], parameters, elements );
        }
    }

    private final void checkForUnusedSettings( final HashMap parameterMap, 
                                               final HashMap elementMap )
        throws TaskException
    {
        if( 0 != parameterMap.size() )
        {
            final String[] namespaces = 
                (String[])parameterMap.keySet().toArray( new String[ 0 ] );

            for( int i = 0; i < namespaces.length; i++ )
            {
                final String namespace = namespaces[ i ];
                final Parameters parameters = (Parameters)parameterMap.get( namespace );
                final ArrayList elementList = (ArrayList)elementMap.remove( namespace );
                
                Configuration[] elements = null;
                
                if( null == elementList ) elements = EMPTY_ELEMENTS;
                else
                {
                    elements = (Configuration[])elementList.toArray( EMPTY_ELEMENTS );
                }
                
                unusedSetting( namespace, parameters, elements );
            }
        }

        if( 0 != elementMap.size() )
        {
            final String[] namespaces = 
                (String[])elementMap.keySet().toArray( new String[ 0 ] );
            
            for( int i = 0; i < namespaces.length; i++ )
            {
                final String namespace = namespaces[ i ];
                final ArrayList elementList = (ArrayList)elementMap.remove( namespace );
                final Configuration[] elements = 
                    (Configuration[])elementList.toArray( EMPTY_ELEMENTS );
                
                unusedSetting( namespace, EMPTY_PARAMETERS, elements );
            }
        }
    }

    private void unusedSetting( final String namespace, 
                                final Parameters parameters, 
                                final Configuration[] elements )
        throws TaskException
    {
        throw new TaskException( "Unused aspect settings for namespace " + namespace + 
                                " (parameterCount=" + parameters.getNames().length + 
                                 " elementCount=" + elements.length + ")" ); 
    }

    private void dispatch( final String namespace, 
                           final Parameters parameters, 
                           final Configuration[] elements )
        throws TaskException
    {
        getAspectManager().dispatchAspectSettings( namespace, parameters, elements );

        if( getLogger().isDebugEnabled() )
        {
            getLogger().debug( "Dispatching Aspect Settings to: " + namespace + 
                               " parameterCount=" + parameters.getNames().length + 
                               " elementCount=" + elements.length ); 
        }
    }

    private final void processElements( final Configuration taskModel, 
                                        final DefaultConfiguration newTaskModel,
                                        final HashMap map )
    {
        final Configuration[] elements = taskModel.getChildren();
        for( int i = 0; i < elements.length; i++ )
        {
            final String name = elements[ i ].getName();
            final int index = name.indexOf( ':' );
            
            if( -1 == index ) 
            {
                newTaskModel.addChild( elements[ i ] );
            }
            else
            {
                final String namespace = name.substring( 0, index );
                final String localName = name.substring( index + 1 );
                final ArrayList elementSet = getElements( namespace, map );
                elementSet.add( elements[ i ] );
            }
        }
    }

    private final void processAttributes( final Configuration taskModel, 
                                          final DefaultConfiguration newTaskModel,
                                          final HashMap map )
    {
        final String[] attributes = taskModel.getAttributeNames();
        for( int i = 0; i < attributes.length; i++ )
        {
            final String name = attributes[ i ];
            final String value = taskModel.getAttribute( name, null );

            final int index = name.indexOf( ':' );
            
            if( -1 == index ) 
            {
                newTaskModel.setAttribute( name, value );
            }
            else
            {
                final String namespace = name.substring( 0, index );
                final String localName = name.substring( index + 1 );
                final Parameters parameters = getParameters( namespace, map );
                parameters.setParameter( localName, value );
            }
        }
    }

    private final ArrayList getElements( final String namespace, final HashMap map )
    {
        ArrayList elements = (ArrayList)map.get( namespace );

        if( null == elements )
        {
            elements = new ArrayList();
            map.put( namespace, elements );
        }

        return elements;
    }

    private final Parameters getParameters( final String namespace, final HashMap map )
    {
        Parameters parameters = (Parameters)map.get( namespace );

        if( null == parameters )
        {
            parameters = new Parameters();
            map.put( namespace, parameters );
        }

        return parameters;
    }

    protected final AspectManager getAspectManager()
    {
        return m_aspectManager;
    }
}
