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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jst.jsf.common.internal.managedobject.IManagedObject;
import org.eclipse.jst.jsf.common.internal.managedobject.ObjectManager.ManagedObjectException;
import org.eclipse.jst.jsf.common.internal.policy.IdentifierOrderedIteratorPolicy;
import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.Namespace;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsf.core.internal.JSFCoreTraceOptions;
import org.eclipse.jst.jsf.designtime.internal.view.model.AbstractTagRegistry;
import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.CompositeTagResolvingStrategy;
import org.eclipse.jst.jsf.facelet.core.internal.FaceletCorePlugin;
import org.eclipse.jst.jsf.facelet.core.internal.FaceletCoreTraceOptions;
import org.eclipse.jst.jsf.facelet.core.internal.cm.FaceletDocumentFactory;
import org.eclipse.jst.jsf.facelet.core.internal.registry.IFaceletTagResolvingStrategy.TLDWrapper;
import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.FaceletTagIndex;
import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.IFaceletTagRecord;
import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.IProjectTaglibDescriptor;
import org.eclipse.jst.jsf.facelet.core.internal.registry.taglib.Listener;
import org.eclipse.jst.jsf.facelet.core.internal.tagmodel.FaceletNamespace;

/**
 * Registry of all facelet tag registries: at most one per project.
 * 
 */
public final class FaceletTagRegistry extends AbstractTagRegistry implements
        IManagedObject
{
    // INSTANCE
    private final ConcurrentLinkedQueue<LibraryOperation>   _changeOperations = new ConcurrentLinkedQueue<LibraryOperation>();

    private final IProject                                  _project;
    private final Map<String, FaceletNamespace>             _nsResolved;
    private final Set<FaceletNamespace>                     _unResolved;
    private final CompositeTagResolvingStrategy<TLDWrapper> _resolver;
    private final FaceletDocumentFactory                    _factory;
    private final LibraryOperationFactory                   _operationFactory = new LibraryOperationFactory(
                                                                                      this);
    private boolean                                         _isInitialized;

    private ChangeJob                                       _changeJob;
    private MyTaglibListener                                _listener;

    FaceletTagRegistry(final IProject project)
    {
        _project = project;
        _nsResolved = new HashMap<String, FaceletNamespace>();
        _unResolved = new HashSet<FaceletNamespace>();

        final List<String> ids = new ArrayList<String>();
        ids.add(FaceletMetaResolvingStrategy.ID);
        ids.add(FaceletTagResolvingStrategy.ID);
        final IdentifierOrderedIteratorPolicy<String> policy = new IdentifierOrderedIteratorPolicy<String>(
                ids);

        // exclude things that are not explicitly listed in the policy. That
        // way preference-based disablement will cause those strategies to
        // be excluded.
        policy.setExcludeNonExplicitValues(true);
        _resolver = new CompositeTagResolvingStrategy<TLDWrapper>(policy);

        _factory = new FaceletDocumentFactory(project);
        // add the strategies
        _resolver.addStrategy(new FaceletTagResolvingStrategy(_project,
                _factory));
        _resolver.addStrategy(new FaceletMetaResolvingStrategy(_project, _factory));

        // _resolver.addStrategy(new DefaultJSPTagResolver(_project));
        // makes sure that a tag element will always be created for any
        // given tag definition even if other methods fail
        // _resolver.addStrategy(new UnresolvedJSPTagResolvingStrategy());
        _changeJob = new ChangeJob(project.getName());
    }

    /**
     * @return a copy of all tag libs, both with namespaces resolved and without
     *         Changing the returned may has no effect on the registry, however
     *         the containned objects are not copies.
     */
    @Override
    public synchronized Collection<FaceletNamespace> getAllTagLibraries()
    {
        final Set<FaceletNamespace> allTagLibraries = new HashSet<FaceletNamespace>();
        if (!_isInitialized)
        {
            try
            {
                initialize(false);
                _isInitialized = true;
            }
            catch (final JavaModelException e)
            {
                FaceletCorePlugin.log("Problem during initialization", e); //$NON-NLS-1$
            }
            catch (final CoreException e)
            {
                FaceletCorePlugin.log("Problem during initialization", e); //$NON-NLS-1$
            }
        }
        allTagLibraries.addAll(_nsResolved.values());
        allTagLibraries.addAll(_unResolved);
        return allTagLibraries;
    }

    private void initialize(boolean fireEvent) throws JavaModelException, CoreException
    {
        if (!_project.exists() || !_project.hasNature(JavaCore.NATURE_ID))
        {
            throw new CoreException(new Status(IStatus.ERROR,
                    FaceletCorePlugin.PLUGIN_ID,
                    "Project either does not exists or is not a java project: " //$NON-NLS-1$
                            + _project));
        }

        final FaceletTagIndex index = FaceletTagIndex.getInstance(_project.getWorkspace());

        IProjectTaglibDescriptor tagDesc;
        try
        {
            tagDesc = index.getInstance(_project);
        }
        catch (ManagedObjectException e)
        {
            throw new CoreException(
                    new Status(
                            IStatus.ERROR,
                            FaceletCorePlugin.PLUGIN_ID,
                            "Error instantiating facelet tag index for project: " + _project.getName(), e)); //$NON-NLS-1$
        }

        if (tagDesc != null)
        {
            for (final IFaceletTagRecord taglib : tagDesc.getTagLibraries())
            {
                initialize(taglib, fireEvent);
            }

            _listener = new MyTaglibListener();
            tagDesc.addListener(_listener);
        }
    }

    FaceletNamespace initialize(final IFaceletTagRecord tagRecord,
            final boolean fireEvent)
    {
        if (JSFCoreTraceOptions.TRACE_JSPTAGREGISTRY_CHANGES)
        {
            FaceletCoreTraceOptions
                    .log("TLDTagRegistry.initialize_TagRecord: Initializing new tld record: " + tagRecord.toString()); //$NON-NLS-1$
        }
        final FaceletNamespace ns = new FaceletNamespace(tagRecord, _resolver);
        _nsResolved.put(tagRecord.getURI(), ns);

        if (fireEvent)
        {
            fireEvent(new TagRegistryChangeEvent(this,
                    TagRegistryChangeEvent.EventType.ADDED_NAMESPACE,
                    Collections.singletonList(ns)));
        }
        return ns;
    }

    void remove(final IFaceletTagRecord tagRecord)
    {
        final FaceletNamespace ns = _nsResolved.remove(tagRecord.getURI());

        if (ns != null)
        {
            fireEvent(new TagRegistryChangeEvent(this,
                    TagRegistryChangeEvent.EventType.REMOVED_NAMESPACE,
                    Collections.singletonList(ns)));
        }
    }

    @Override
    public synchronized Namespace getTagLibrary(final String uri)
    {
        // TODO:
        getAllTagLibraries();
        return _nsResolved.get(uri);
    }

    @Override
    protected Job getRefreshJob(final boolean flushCaches)
    {
        return new Job("Refreshing Facelet tag registry for " + _project.getName()) //$NON-NLS-1$
        {
            @Override
            protected IStatus run(final IProgressMonitor monitor)
            {
//                if (FaceletCoreTraceOptions.TRACE_JSPTAGREGISTRY)
//                {
//                    JSFCoreTraceOptions.log("FaceletTagRegistry.refresh: start"); //$NON-NLS-1$
//                }

                synchronized (FaceletTagRegistry.this)
                {
                    if (JSFCoreTraceOptions.TRACE_JSPTAGREGISTRY)
                    {
                        JSFCoreTraceOptions
                                .log("FaceletTagRegistry.refresh: start"); //$NON-NLS-1$
                    }

                    final List<Namespace> namespaces = new ArrayList(
                            _nsResolved.values());

                    if (flushCaches)
                    {
                        FaceletTagIndex.getInstance(_project.getWorkspace()).flush(_project);
                    }
                    // if we aren't flushing caches, then check point the
                    // current namespace data, so it isn't lost when we clear
                    // THE NAMESPACES
                    else
                    {
                        checkpoint();
                    }

                    _nsResolved.clear();

                    fireEvent(new TagRegistryChangeEvent(FaceletTagRegistry.this,
                            TagRegistryChangeEvent.EventType.REMOVED_NAMESPACE,
                            namespaces));
                    try
                    {
                        initialize(true);
                    }
                    catch (JavaModelException e)
                    {
                        return new Status(IStatus.ERROR, FaceletCorePlugin.PLUGIN_ID, "Problem refreshing registry", e); //$NON-NLS-1$
                    }
                    catch (CoreException e)
                    {
                        return new Status(IStatus.ERROR, FaceletCorePlugin.PLUGIN_ID, "Problem refreshing registry", e); //$NON-NLS-1$
                    }

//                    if (JSFCoreTraceOptions.TRACE_JSPTAGREGISTRY)
//                    {
//                        JSFCoreTraceOptions
//                                .log("TLDTagRegistry.refresh: finished");
//                    }
                    return Status.OK_STATUS;
                }
            }
        };
    }

    private class MyTaglibListener extends Listener
    {
        @Override
        public void changed(TaglibChangedEvent event)
        {
            switch (event.getChangeType())
            {
                case ADDED:
                    addLibraryOperation(_operationFactory
                            .createAddOperation(event.getNewValue()));
                break;
                case CHANGED:
                    addLibraryOperation(_operationFactory
                            .createChangeOperation(event.getNewValue()));
                break;
                case REMOVED:
                    addLibraryOperation(_operationFactory
                            .createRemoveOperation(event.getOldValue()));
                break;
            }
        }
    }

    private void addLibraryOperation(final LibraryOperation operation)
    {
        _changeOperations.add(operation);
        _changeJob.schedule();
    }

    private class ChangeJob extends Job
    {
        private int _rescheduleTime = -1;

        public ChangeJob(final String projectName)
        {
            super("Update job for project " + projectName); //$NON-NLS-1$
        }

        @Override
        protected IStatus run(final IProgressMonitor monitor)
        {
            synchronized (FaceletTagRegistry.this)
            {
                _rescheduleTime = -1;

                LibraryOperation operation = null;
                final MultiStatus multiStatus = new MultiStatus(
                        JSFCorePlugin.PLUGIN_ID, 0, "Result of change job", //$NON-NLS-1$
                        new Throwable());
                while ((operation = _changeOperations.poll()) != null)
                {
                    _rescheduleTime = 10000; // ms

                    operation.run();
                    multiStatus.add(operation.getResult());
                }

                if (_rescheduleTime >= 0 && !monitor.isCanceled())
                {
                    // if any operations were found on this run, reschedule
                    // to run again in 10seconds based on the assumption that
                    // events may be coming in bursts
                    schedule(_rescheduleTime);
                }

                return multiStatus;
            }
        }
    }

    @Override
    protected void doDispose()
    {
        if (_listener != null)
        {
            FaceletTagIndex index = FaceletTagIndex.getInstance(_project.getWorkspace());
            try
            {
                IProjectTaglibDescriptor instance = index.getInstance(_project);
                instance.removeListener(_listener);
            }
            catch (ManagedObjectException e)
            {
                FaceletCorePlugin
                        .log(
                                "Disposing facelet tag registry for project: " + _project.getName(), e); //$NON-NLS-1$
            }

            _nsResolved.clear();
        }
    }

    @Override
    protected void cleanupPersistentState()
    {
        // TODO ??

    }

    public void checkpoint()
    {
        // TODO ??

    }
}
