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

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jst.jsf.common.internal.util.JarUtilities;
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.IJarBasedJSFResource;
import org.eclipse.jst.jsf.designtime.internal.resources.IWorkspaceJSFResourceFragment;
import org.eclipse.jst.jsf.designtime.internal.resources.WorkspaceJSFResourceContainer;
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;
import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.faceletTaglib.FaceletTaglibFactory;
import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.faceletTaglib.FaceletTaglibTag;

/**
 * A facelet tag record is derived from a JSF locatable resource (ezcomp).
 * 
 * @author cbateman
 * 
 */
public class JSFResourceBasedTagRecord extends FaceletTagRecord
{
    private final List<FaceletTaglibTag> _tags;
    private final String _uri;

    /**
     * @param uri
     * @param tags
     * @param descriptor
     */
    public JSFResourceBasedTagRecord(final String uri,
            final List<FaceletTaglibTag> tags,
            final TagRecordDescriptor descriptor)
    {
        super(descriptor);
        _uri = uri;
        _tags = tags;
    }

    /**
     * 
     */
    private static final long serialVersionUID = 5944923828112777373L;

    public int getNumTags()
    {
        return _tags.size();
    }

    @Override
    public String getURI()
    {
        return _uri;
    }

    @Override
    public FaceletTaglibTag getTag(final String name)
    {
        for (final FaceletTaglibTag tag : _tags)
        {
            if (tag.getTagName().equals(name))
            {
                return tag;
            }
        }
        return null;
    }

    @Override
    public Collection<? extends FaceletTaglibTag> getTags()
    {
        return Collections.unmodifiableCollection(_tags);
    }

    /**
     * Merge my tags with 'withThese'. Tags in my list will be replaced with
     * those in 'withThese' if their names match.
     * 
     * @param withThese
     */
    /* package */JSFResourceBasedTagRecord mergeTags(
            final List<FaceletTaglibTag> withThese)
    {
        final List<FaceletTaglibTag> tags = new ArrayList<FaceletTaglibTag>(
                _tags);
        for (final FaceletTaglibTag mergeTag : withThese)
        {
            final FaceletTaglibTag tag = getTag(mergeTag.getTagName());
            if (tag != null)
            {
                tags.remove(tag);
            }
            tags.add(mergeTag);
        }
        return new JSFResourceBasedTagRecord(_uri, tags, getDescriptor());
    }

    /* package */JSFResourceBasedTagRecord removeTags(
            final List<FaceletTaglibTag> removeThese)
    {
        final List<FaceletTaglibTag> tags = new ArrayList<FaceletTaglibTag>(
                _tags);
        for (final FaceletTaglibTag mergeTag : removeThese)
        {
            final FaceletTaglibTag tag = getTag(mergeTag.getTagName());
            if (tag != null)
            {
                tags.remove(tag);
            }
        }
        return new JSFResourceBasedTagRecord(_uri, tags, getDescriptor());
    }

    /**
     * A builder for tag record.
     * 
     * @author cbateman
     * 
     */
    public static class Builder
    {
        private static final LibEntry WHOLE_LIBRARY = new LibEntry(null);
        private static final JSFResourceBasedTagRecord WHOLE_LIB_RECORD = new JSFResourceBasedTagRecord(null, Collections.EMPTY_LIST, null);
        private final Map<String, LibEntry> _tags = new HashMap<String, LibEntry>();
        private static final String FACELET_FILE_CONTENT_TYPE = "org.eclipse.wst.html.core.htmlsource"; //$NON-NLS-1$

        /**
         * @param jsfResource
         * @param changeType
         */
        public void addTag(final IJSFResource jsfResource,
                final CHANGE_TYPE changeType)
        {
            final String libraryName = jsfResource.getId().getLibraryName();
            if (libraryName == null)
            {
                return;
            }
            final String uri = String.format(
                    "http://java.sun.com/jsf/composite/%s", libraryName); //$NON-NLS-1$
            LibEntry tags = _tags.get(uri);
            if (tags == null)
            {
                tags = new LibEntry(createDescriptor(jsfResource));
                _tags.put(uri, tags);
            }
            final String resourceName = jsfResource.getId().getResourceName();
            final IPath resourceNamePath = new Path(resourceName)
                    .removeFileExtension();
            final FaceletTaglibTag tag = FaceletTaglibFactory.eINSTANCE
                    .createFaceletTaglibTag();
            tag.setTagName(resourceNamePath.toString());
            switch (changeType)
            {
                case ADDED:
                case CHANGED:
                    // only add to the list on a add/change if the resource
                    // exists and is the right type
                    if (jsfResource.isAccessible()
                            && jsfResource
                                    .isContentType(FACELET_FILE_CONTENT_TYPE))
                    {
                        tags.addTag(tag);
                    }
                break;
                case REMOVED:
                    // add all comers to the remove list. There will only be
                    // removal
                    // on merge if ADDED/CHANGED path decided they should be
                    // there.
                    tags.addTag(tag);
                break;
            }
        }

        /**
         * @param jsfResource
         * @param changeType
         */
        public void addLibrary(final IJSFResourceContainer jsfResource,
                final CHANGE_TYPE changeType)
        {
            final String libraryName = jsfResource.getId().getLibraryName();
            if (libraryName == null || libraryName.trim().length() == 0)
            {
                return;
            }
            final String uri = String.format(
                    "http://java.sun.com/jsf/composite/%s", libraryName); //$NON-NLS-1$
            if (changeType == CHANGE_TYPE.REMOVED)
            {
                _tags.put(uri, WHOLE_LIBRARY);
            } else
            {
                LibEntry tags = _tags.get(uri);
                if (tags == null)
                {
                    tags = new LibEntry(createDescriptor(jsfResource));
                    _tags.put(uri, tags);
                }
            }
        }

        /**
         * @return the built list of tag records.
         */
        public Map<String, JSFResourceBasedTagRecord> build()
        {
            final Map<String, JSFResourceBasedTagRecord> records = new HashMap<String, JSFResourceBasedTagRecord>();
            for (final Map.Entry<String, LibEntry> entry : _tags
                    .entrySet())
            {
                if (entry.getValue() == WHOLE_LIBRARY)
                {
                    records.put(entry.getKey(), WHOLE_LIB_RECORD);
                }
                else
                {
                    final String uri = entry.getKey();
                    final List<FaceletTaglibTag> tags = new ArrayList<FaceletTaglibTag>(entry.getValue().getTags());
                    final TagRecordDescriptor descriptor = entry.getValue().getDescriptor();
                    final JSFResourceBasedTagRecord newRecord = new JSFResourceBasedTagRecord(
                            uri, tags, descriptor);
                    records.put(entry.getKey(), newRecord);
                }
            }
            return records;
        }

        /**
         * @param locator
         * @param records
         * @return a list of taglib change events that reflect what will happen
         *         when my tags are merged into the map 'records'.
         */
        public List<TaglibChangedEvent> createMerge(
                final AbstractFaceletTaglibLocator locator,
                final Map<String, JSFResourceBasedTagRecord> records)
        {
            final Map<String, JSFResourceBasedTagRecord> newRecords = build();
            final List<TaglibChangedEvent> mergeEvents = new ArrayList<TaglibChangedEvent>();
            for (final Map.Entry<String, JSFResourceBasedTagRecord> entry : newRecords
                    .entrySet())
            {
                TaglibChangedEvent event = null;
                if (!records.containsKey(entry.getKey()))
                {
                    event = new TaglibChangedEvent(locator, null,
                            entry.getValue(), CHANGE_TYPE.ADDED);
                } else
                {
                    final JSFResourceBasedTagRecord oldRecord = records
                            .get(entry.getKey());
                    final JSFResourceBasedTagRecord newRecord = oldRecord
                            .mergeTags(entry.getValue()._tags);
                    event = new TaglibChangedEvent(locator, oldRecord,
                            newRecord, CHANGE_TYPE.CHANGED);
                }
                mergeEvents.add(event);
            }
            return mergeEvents;
        }

        /**
         * @param locator
         * @param records
         * @return a list of change events that will result from removing my
         *         _tags from records.
         */
        public List<TaglibChangedEvent> createRemove(
                final AbstractFaceletTaglibLocator locator,
                final Map<String, JSFResourceBasedTagRecord> records)
        {
            final Map<String, JSFResourceBasedTagRecord> newRecords = build();
            final List<TaglibChangedEvent> mergeEvents = new ArrayList<TaglibChangedEvent>();
            for (final Map.Entry<String, JSFResourceBasedTagRecord> entry : newRecords
                    .entrySet())
            {
                TaglibChangedEvent event = null;
                final JSFResourceBasedTagRecord oldRecord = records.get(entry
                        .getKey());
                if (oldRecord != null)
                {
                    final JSFResourceBasedTagRecord record = entry.getValue();
                    if (record == WHOLE_LIB_RECORD)
                    {
                        event = new TaglibChangedEvent(locator, oldRecord,
                                null, CHANGE_TYPE.REMOVED);
                    } else
                    {
                        final JSFResourceBasedTagRecord newRecord = oldRecord
                                .removeTags(entry.getValue()._tags);
                        event = new TaglibChangedEvent(locator, oldRecord,
                                newRecord, CHANGE_TYPE.CHANGED);
                    }
                }
                if (event != null)
                {
                    mergeEvents.add(event);
                }
            }
            return mergeEvents;
        }

        /**
         * @param events
         * @param withThese
         * @return a new merged map that contains withThese plus everything
         *         here.
         */
        public Map<String, JSFResourceBasedTagRecord> merge(
                final List<TaglibChangedEvent> events,
                final Map<String, JSFResourceBasedTagRecord> withThese)
        {
            final Map<String, JSFResourceBasedTagRecord> newMap = new HashMap<String, JSFResourceBasedTagRecord>(
                    withThese);
            for (final TaglibChangedEvent event : events)
            {
                switch (event.getChangeType())
                {
                    case ADDED:
                    case CHANGED:
                    {
                        final IFaceletTagRecord newRecord = event.getNewValue();
                        // doubles as null check
                        if (newRecord instanceof JSFResourceBasedTagRecord)
                        {
                            newMap.put(newRecord.getURI(),
                                    (JSFResourceBasedTagRecord) newRecord);
                        }
                    }
                    break;
                    case REMOVED:
                    {
                        final IFaceletTagRecord oldRecord = event.getOldValue();
                        if (oldRecord != null)
                        {
                            newMap.remove(oldRecord.getURI());
                        }
                    }
                    break;
                }
            }
            return newMap;
        }

        private TagRecordDescriptor createDescriptor(final IJSFResourceFragment resource)
        {
            if (resource instanceof IWorkspaceJSFResourceFragment)
            {
                if (resource instanceof WorkspaceJSFResourceContainer)
                {
                    final IResource res = ((WorkspaceJSFResourceContainer)resource).getResource();
                    return new WorkspaceTagRecordDescriptor((IFolder) res);
                }
                final IResource res = ((IWorkspaceJSFResourceFragment) resource)
                        .getResource();
                return new WorkspaceTagRecordDescriptor((IFile) res);
            } else if (resource instanceof IJarBasedJSFResource)
            {
                final URL jarURL = ((IJarBasedJSFResource) resource)
                        .getJarURL();
                final File file = JarUtilities.INSTANCE.getFile(jarURL);
                if (file != null)
                {
                    final String absolutePath = file.getAbsolutePath();
                    final String jarEntryName = ((IJarBasedJSFResource) resource)
                            .getJarEntryName();
                    return new JarTagRecordDescriptor(new Path(absolutePath),
                            jarEntryName);
                }
            }
            return null;
        }

        private static class LibEntry
        {
            private final TagRecordDescriptor _descriptor;
            private final List<FaceletTaglibTag> _tags;

            /**
             * @param descriptor
             */
            public LibEntry(final TagRecordDescriptor descriptor)
            {
                super();
                _descriptor = descriptor;
                _tags = new ArrayList<FaceletTaglibTag>();
            }

            public TagRecordDescriptor getDescriptor()
            {
                return _descriptor;
            }

            public void addTag(final FaceletTaglibTag tag)
            {
                _tags.add(tag);
            }

            public List<FaceletTaglibTag> getTags()
            {
                return Collections.unmodifiableList(_tags);
            }
        }
    }
}
