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.ILock;
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 final ILock										_lock = Job.getJobManager().newLock();
    private volatile 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>();
        
//Commenting out this strategy because of current circular dependency with facelet md locating.  See FaceletNamespaceMetaDataLocator.
//        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));
        
//Commenting out this strategy because of current circular dependency with facelet md locating.  See FaceletNamespaceMetaDataLocator.
//        _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 Collection<FaceletNamespace> getAllTagLibraries()
    {
    	boolean setEndRule = false;
    	try {
			final Set<FaceletNamespace> allTagLibraries = new HashSet<FaceletNamespace>();
			
			if (!_isInitialized)
			{
				// preemptive project rule setting here ensures consistent lock ordering
				// and gives the opportunity for the other thread having the project lock
				// to finish before we enter synchronization block created with reentrant 
				// lock below
				// NOTE: it is essential to have _lock.acquire() after project rule start
				// NOTE: if current thread already has any rule, do not start project rule
				if(Job.getJobManager().currentRule() == null){
					Job.getJobManager().beginRule(_project, null);
					setEndRule = true;
				}				
				_lock.acquire();
				
				// double check after sync block if no one else entered "if(!_isInitialized)"
				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$
					}
				}
			}else{
				_lock.acquire();
			}
			allTagLibraries.addAll(_nsResolved.values());
			allTagLibraries.addAll(_unResolved);
			return allTagLibraries;
    	} finally {
    		_lock.release();
    		if (setEndRule){
    			Job.getJobManager().endRule(_project);
    		}
    	}
    }

    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())
            {
            	if (taglib.getURI() != null)
            		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 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$
//                }
            	boolean setEndRule = false;
                try
                {
                	if(Job.getJobManager().currentRule() == null){
    					Job.getJobManager().beginRule(_project, null);
    					setEndRule = true;
    				}
                	_lock.acquire();
                    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;
                } finally {
                	_lock.release();
                	if (setEndRule){
                		Job.getJobManager().endRule(_project);
                	}
                }
            }
        };
    }

    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$
            // preemptive project rule setting here ensures consistent lock ordering
            // and gives the opportunity for the other thread having the project lock
            // to finish before we enter synchronization block created with reentrant 
            // lock below
            // NOTE: it is essential to have _lock.acquire() after project rule start
            setRule(_project);
        }

        @Override
        protected IStatus run(final IProgressMonitor monitor)
        {
            try 
            {
            	_lock.acquire();
                _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;
            } finally {
            	_lock.release();
            }
        }
    }

    @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 ??

    }

}
