package org.eclipse.jst.jsf.facelet.core.internal.registry.taglib;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.jst.jsf.common.internal.locator.ILocatorProvider;
import org.eclipse.jst.jsf.designtime.internal.resources.IJSFResource;
import org.eclipse.jst.jsf.designtime.internal.resources.IJSFResourceContainer;
import org.eclipse.jst.jsf.designtime.internal.resources.IJSFResourceFragment;
import org.eclipse.jst.jsf.designtime.internal.resources.IJSFResourceFragment.Type;
import org.eclipse.jst.jsf.designtime.internal.resources.IJSFResourceLocator;
import org.eclipse.jst.jsf.designtime.internal.resources.JSFResourceChangeListener;
import org.eclipse.jst.jsf.designtime.internal.resources.JSFResourceContainer;
import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.JSFResourceBasedTagRecord.Builder;
import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.Listener.TaglibChangedEvent;
import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.Listener.TaglibChangedEvent.CHANGE_TYPE;

/**
 * A taglib locator that locates composite components, which a located as a type
 * of JSF locatable resource.
 * 
 * @author cbateman
 * 
 */
public class CompositeComponentTaglibLocator extends
        AbstractFaceletTaglibLocator
{
    private final class ResourceLocatorChangeListener extends
            JSFResourceChangeListener
    {
        @Override
        public void changed(final JSFResourceChangedEvent event)
        {
            final Builder builder = new Builder();
            switch (event.getChangeType())
            {
                case ADDED:
                case CHANGED:
                {
                    handleAddAndChange(event, builder);
                }
                break;
                case REMOVED:
                {
                    handleRemove(event, builder);
                }
                break;
            }
        }

        private void handleRemove(final JSFResourceChangedEvent event,
                final Builder builder)
        {
        	//Bug 324234 - NPE from CompositeComponentTaglibLocator
        	if (event != null)
        	{
	            IJSFResourceFragment oldValue = event.getOldValue();
	            if (oldValue != null)
	            {
	            	Type type = oldValue.getType();
	            	if (type != null)
	            	{
			            List<TaglibChangedEvent> events = Collections.EMPTY_LIST;
			            switch (type)
			            {
			                case RESOURCE:
			                {
			                    events = handleRemoveResource(event, builder);
			                }
			                break;
			                case CONTAINER:
			                {
			                    events = handleRemoveContainer(event, builder);
			                }
			                break;
			            }
			            _records = builder.merge(events, _records);
			            for (final TaglibChangedEvent fireEvent : events)
			            {
			                fireChangeEvent(fireEvent);
			            }
	            	}
	            }
        	}
        }

        private List<TaglibChangedEvent> handleRemoveContainer(
                final JSFResourceChangedEvent event, final Builder builder)
        {
            final IJSFResourceFragment oldValue = event.getOldValue();
            builder.addLibrary((IJSFResourceContainer) oldValue,
                    CHANGE_TYPE.REMOVED);
            return builder.createRemove(CompositeComponentTaglibLocator.this,
                    _records);
        }

        private List<TaglibChangedEvent> handleRemoveResource(
                final JSFResourceChangedEvent event, final Builder builder)
        {
            final IJSFResourceFragment oldValue = event.getOldValue();
            builder.addTag((IJSFResource) oldValue, CHANGE_TYPE.REMOVED);
            return builder.createRemove(CompositeComponentTaglibLocator.this,
                    _records);
        }

        private void handleAddAndChange(final JSFResourceChangedEvent event,
                final Builder builder)
        {
            List<TaglibChangedEvent> events = Collections.EMPTY_LIST;

            switch (event.getNewValue().getType())
            {
                case CONTAINER:
                    // if it's a fragment handle as a possible library add
                    events = handleFolderAddChange(event, builder);
                break;
                case RESOURCE:
                    // otherwise, handle as a file add.
                    events = handleFileAddChange(event, builder);
                break;
            }

            _records = builder.merge(events, _records);

            for (final TaglibChangedEvent fireEvent : events)
            {
                fireChangeEvent(fireEvent);
            }
        }

        private List<TaglibChangedEvent> handleFolderAddChange(
                final JSFResourceChangedEvent event, final Builder builder)
        {
            final JSFResourceContainer newValue = (JSFResourceContainer) event
                    .getNewValue();
            builder.addLibrary(newValue, CHANGE_TYPE.ADDED);
            return builder.createMerge(CompositeComponentTaglibLocator.this,
                    _records);
        }

        private List<TaglibChangedEvent> handleFileAddChange(
                final JSFResourceChangedEvent event, final Builder builder)
        {
            final IJSFResource newValue = (IJSFResource) event.getNewValue();
            builder.addTag(newValue, CHANGE_TYPE.ADDED);
            return builder.createMerge(CompositeComponentTaglibLocator.this,
                    _records);
        }
    }

    /**
     * the id of the locator strategy.
     */
    public static final String ID = CompositeComponentTaglibLocator.class
            .getCanonicalName();
    private static final String DISPLAY_NAME = "Composite Composite Tag Lib Locator"; //$NON-NLS-1$
    private final ILocatorProvider<IJSFResourceLocator> _locatorProvider;
    private Map<String, JSFResourceBasedTagRecord> _records;
    private final ResourceLocatorChangeListener _listener;

    /**
     * @param locatorProvider
     */
    public CompositeComponentTaglibLocator(
            final ILocatorProvider<IJSFResourceLocator> locatorProvider)
    {
        super(ID, DISPLAY_NAME);
        _locatorProvider = locatorProvider;
        _locatorProvider.initialize();
        _listener = new ResourceLocatorChangeListener();
    }

    @Override
    public void start(final IProject initialContext)
    {
        for (final IJSFResourceLocator locator : _locatorProvider.getLocators())
        {
            locator.start(initialContext);
            locator.addListener(_listener);
        }

        final Builder builder = new Builder();
        for (final IJSFResourceLocator locator : _locatorProvider.getLocators())
        {
            final List<IJSFResourceFragment> resources = locator
                    .locate(initialContext);
            for (final IJSFResourceFragment resource : resources)
            {
                if (resource.getType() == Type.RESOURCE)
                {
                    builder.addTag((IJSFResource) resource, CHANGE_TYPE.ADDED);
                }
            }
        }
        _records = builder.build();

        super.start(initialContext);
    }

    @Override
    public void stop()
    {
        for (final IJSFResourceLocator locator : _locatorProvider.getLocators())
        {
            locator.stop();
        }
        super.stop();
    }

    @Override
    protected Map<String, ? extends IFaceletTagRecord> doLocate(
            final IProject context)
    {
        return Collections.unmodifiableMap(_records);
    }
}
