/*=============================================================================#
 # Copyright (c) 2015, 2021 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.internal.r.console.core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.IntArrayList;
import org.eclipse.statet.jcommons.collections.IntList;
import org.eclipse.statet.jcommons.status.ErrorStatus;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.StatusException;
import org.eclipse.statet.jcommons.status.Statuses;

import org.eclipse.statet.internal.r.rdata.REnvironmentVar;
import org.eclipse.statet.internal.r.rdata.RReferenceVar;
import org.eclipse.statet.internal.r.rdata.VirtualMissingVar;
import org.eclipse.statet.r.console.core.AbstractRController;
import org.eclipse.statet.r.console.core.RProcessREnvironment;
import org.eclipse.statet.r.console.core.RWorkspace;
import org.eclipse.statet.r.core.data.CombinedRElement;
import org.eclipse.statet.r.core.data.CombinedRList;
import org.eclipse.statet.r.core.model.RElementName;
import org.eclipse.statet.r.nico.ICombinedRDataAdapter;
import org.eclipse.statet.rj.data.RCharacterStore;
import org.eclipse.statet.rj.data.RDataUtils;
import org.eclipse.statet.rj.data.REnvironment;
import org.eclipse.statet.rj.data.RObject;
import org.eclipse.statet.rj.data.RReference;
import org.eclipse.statet.rj.data.RVector;
import org.eclipse.statet.rj.data.UnexpectedRDataException;
import org.eclipse.statet.rj.services.RService;


public class RObjectDB {
	
	
	private static final Set<Long> NO_ENVS_SET= Collections.emptySet();
	
	
	private static class NamespaceEntry {
		
		private volatile VirtualMissingVar na;
		
		private REnvironmentVar namespaceEnv;
		
		private REnvironmentVar namespaceExports;
		
		private REnvironmentVar packageEnv;
		
	}
	
	private static class EnvironmentEntry {
		
		private final REnvironmentVar env;
		
		private byte checking;
		private byte checked;
		
		public EnvironmentEntry(final REnvironmentVar env) {
			this.env= env;
		}
		
	}
	
	
	private static boolean isNamespaceEnv(final RElementName elementName) {
		return (elementName != null && elementName.getType() == RElementName.SCOPE_NS_INT
				&& elementName.getNextSegment() == null );
	}
	
	private static CombinedRElement first(final CombinedRElement first, final CombinedRElement second) {
		return (first != null) ? first : second;
	}
	
	private static final byte UPTODATE= RWorkspace.RESOLVE_UPTODATE;
	private static final byte RECURSIVE= RWorkspace.RESOLVE_RECURSIVE;
	private static final byte RECURSIVE_UPTODATE= RECURSIVE << 1;
	
	/** workspace flags -> this mode */
	public static byte toResolveMode(int resolve) {
		resolve&= (UPTODATE | RECURSIVE);
		if (resolve == (UPTODATE | RECURSIVE)) {
			resolve|= RECURSIVE_UPTODATE;
		}
		return (byte) resolve;
	}
	
	
	private final RWorkspace workspace;
	
	private final ConcurrentHashMap<Long, EnvironmentEntry> envsMap= new ConcurrentHashMap<>();
	
	private int searchEnvsStamp;
	private List<REnvironmentVar> searchEnvs;
	private List<? extends RProcessREnvironment> searchEnvsPublic;
	
	private int lazyEnvsStamp;
	private Set<Long> lazyEnvs;
	
	private final ConcurrentHashMap<String, RObjectDB.NamespaceEntry> namespaceMap= new ConcurrentHashMap<>();
	private List<String> forceUpdatePkgNames;
	
	private RObjectDB previousDB;
	private byte resolveMode;
	
	private ICombinedRDataAdapter r;
	
	
	public RObjectDB(final RWorkspace workspace, final int stamp,
			final AbstractRController r, final ProgressMonitor m) {
		this.workspace= r.getWorkspaceData();
		
		this.searchEnvsStamp= stamp;
		this.searchEnvsPublic= Collections.emptyList();
		this.lazyEnvs= NO_ENVS_SET;
		
		updateLazyEnvs(r, m);
	}
	
	
	public List<? extends RProcessREnvironment> getSearchEnvs() {
		return this.searchEnvsPublic;
	}
	
	public int getSearchEnvsStamp() {
		return this.searchEnvsStamp;
	}
	
	public int getSearchEnvsElementCount() {
		int count= 0;
		for (final REnvironmentVar env : this.searchEnvs) {
			if (env != null) {
				final long l= env.getLength();
				if (l > 0) {
					count+= l;
				}
			}
		}
		return count;
	}
	
	public REnvironmentVar getEnv(final Long handle) {
		final EnvironmentEntry entry= this.envsMap.get(handle);
		return (entry != null) ? entry.env : null;
	}
	
	public CombinedRElement getNamespaceEnv(final String name) {
		if (name != null) {
			final RObjectDB.NamespaceEntry entry= this.namespaceMap.get(name);
			if (entry != null) {
				return first(entry.na, entry.namespaceEnv);
			}
		}
		return null;
	}
	
	public CombinedRElement getNamespacePub(final String name) {
		if (name != null) {
			final RObjectDB.NamespaceEntry entry= this.namespaceMap.get(name);
			if (entry != null) {
				return first(entry.na, entry.namespaceExports);
			}
		}
		return null;
	}
	
	public boolean isNamespaceLoaded(final String name) {
		if (name != null) {
			final RObjectDB.NamespaceEntry entry= this.namespaceMap.get(name);
			return (entry != null && entry.na == null);
		}
		return false;
	}
	
	public CombinedRElement getPackageEnv(final String name) {
		if (name != null) {
			final RObjectDB.NamespaceEntry entry= this.namespaceMap.get(name);
			if (entry != null) {
				return first(entry.na, entry.packageEnv);
			}
		}
		return null;
	}
	
	public REnvironmentVar getSearchEnv(final String name) {
		if (name != null) {
			for (final REnvironmentVar env : this.searchEnvs) {
				final RElementName elementName= env.getElementName();
				if (elementName != null && elementName.getType() == RElementName.SCOPE_SEARCH_ENV
						&& name.equals(elementName.getSegmentName())) {
					return env;
				}
			}
		}
		return null;
	}
	
	public CombinedRElement getByName(final RElementName name) {
		switch (name.getType()) {
		case RElementName.SCOPE_NS:
			return getNamespacePub(name.getSegmentName());
		case RElementName.SCOPE_NS_INT:
			return getNamespaceEnv(name.getSegmentName());
		case RElementName.SCOPE_SEARCH_ENV:
			return getSearchEnv(name.getSegmentName());
		case RElementName.SCOPE_PACKAGE:
			return getPackageEnv(name.getSegmentName());
		default:
			return null;
		}
	}
	
	
	public int getLazyEnvsStamp() {
		return this.lazyEnvsStamp;
	}
	
	public void updateLazyEnvs(final AbstractRController r, final ProgressMonitor m) {
		if (this.envsMap != null && !this.envsMap.isEmpty() && !this.lazyEnvs.isEmpty()) {
			this.envsMap.keySet().removeAll(this.lazyEnvs);
		}
		this.lazyEnvsStamp= r.getChangeStamp();
		final Set<Long> list= r.getLazyEnvironments(m);
		this.lazyEnvs= (list != null && !list.isEmpty()) ? list : NO_ENVS_SET;
	}
	
	public List<REnvironmentVar> update(
			final Set<RElementName> envs, RObjectDB previous, final boolean force,
			final ICombinedRDataAdapter r, final ProgressMonitor m) throws StatusException {
		this.r= r;
		try {
			updateSearchList(m);
			updateNamespaceList(m);
			
			if (m.isCanceled()) {
				return null;
			}
			
			List<String> forcePkgNames= null;
			if (previous != null) {
				if (force) {
					previous= null;
				}
				else {
					forcePkgNames= previous.forceUpdatePkgNames;
				}
			}
			
			final IntList updateList= createUpdateIdxs(envs, previous, forcePkgNames);
			final List<REnvironmentVar> updateEnvs= createUpdateEnvs(updateList, m);
			
			updateEnvMap(updateEnvs, previous, forcePkgNames, m);
			
			if (previous != null) {
				for (final Map.Entry<String, RObjectDB.NamespaceEntry> entry : previous.namespaceMap.entrySet()) {
					final String name= entry.getKey();
					if (forcePkgNames != null && forcePkgNames.contains(name)) {
						continue;
					}
					
					final RObjectDB.NamespaceEntry oldEntry= entry.getValue();
					final RObjectDB.NamespaceEntry newEntry= this.namespaceMap.get(name);
					if (oldEntry == null || oldEntry.na != null || newEntry == null) {
						continue;
					}
					
					if (newEntry.namespaceEnv == null) {
						newEntry.namespaceEnv= oldEntry.namespaceEnv;
					}
					if (newEntry.namespaceExports == null) {
						newEntry.namespaceExports= oldEntry.namespaceExports;
					}
				}
			}
			
			return updateEnvs;
		}
		catch (final UnexpectedRDataException e) {
			throw new StatusException(new ErrorStatus(RConsoleCorePlugin.BUNDLE_ID,
					"Unexpected return value from R.",
					e ));
		}
		finally {
			this.r= null;
		}
	}
	
	private void updateSearchList(final ProgressMonitor m) throws StatusException,
			UnexpectedRDataException {
		this.searchEnvsStamp= this.r.getChangeStamp();
		this.searchEnvs= new ArrayList<>();
		this.searchEnvsPublic= Collections.unmodifiableList(this.searchEnvs);
		final RVector<RCharacterStore> searchObj= RDataUtils.checkRCharVector(
				this.r.evalData("base::search()", m)); //$NON-NLS-1$
		
		final RCharacterStore namesData= searchObj.getData();
		for (int i= 0; i < namesData.getLength(); i++) {
			if (namesData.isNA(i)) {
				continue;
			}
			final String name= namesData.getChar(i);
			this.searchEnvs.add(new REnvironmentVar(name, true, null, null));
		}
	}
	
	private void updateNamespaceList(final ProgressMonitor m)
			throws StatusException, UnexpectedRDataException {
		final RVector<RCharacterStore> searchObj= RDataUtils.checkRCharVector(
				this.r.evalData("base::loadedNamespaces()", m )); //$NON-NLS-1$
		
		final RCharacterStore namesData= searchObj.getData();
		for (int i= 0; i < namesData.getLength(); i++) {
			if (namesData.isNA(i)) {
				continue;
			}
			final String name= namesData.getChar(i);
			getNamespaceEntry(name);
		}
	}
	
	public IntList createUpdateIdxs(final Set<RElementName> envs,
			final RObjectDB previous, final List<String> forcePkgNames) {
		final IntList updateIdxs= new IntArrayList(this.searchEnvs.size());
		if (previous == null) {
			for (int newIdx= 0; newIdx < this.searchEnvs.size(); newIdx++) {
				updateIdxs.add(newIdx);
			}
		}
		else {
			// reuse environments until we found a new or any none-package item
			int newIdx= this.searchEnvs.size() - 1;
			for (int oldIdx= previous.searchEnvs.size(); newIdx >= 0; newIdx--) {
				final REnvironmentVar current= this.searchEnvs.get(newIdx);
				final String pkgName;
				if (current.getSpecialType() > 0 && current.getSpecialType() <= REnvironment.ENVTYPE_PACKAGE
						&& (forcePkgNames == null || (pkgName= getPkgName(current)) == null
								|| !forcePkgNames.contains(pkgName) )) {
					final int j= previous.searchEnvs.indexOf(current);
					if (j >= 0 && j < oldIdx) {
						oldIdx= j;
						if (envs != null && envs.contains(current.getElementName())) {
							updateIdxs.add(newIdx);
						}
						else {
							this.searchEnvs.set(newIdx, previous.searchEnvs.get(oldIdx));
						}
						continue;
					}
				}
				break;
			}
			
			for (; newIdx >= 0; newIdx--) {
				updateIdxs.add(newIdx);
			}
		}
		return updateIdxs;
	}
	
	private List<REnvironmentVar> createUpdateEnvs(final IntList updateIdxs,
			final ProgressMonitor m) throws StatusException {
		final ArrayList<REnvironmentVar> updateEnvs= new ArrayList<>(updateIdxs.size());
		for (int idx= 0; idx < updateIdxs.size(); idx++) {
			if (m.isCanceled()) {
				throw new StatusException(Statuses.CANCEL_STATUS);
			}
			// Debug code
//			if (item.getName().equals("methods")) {
			{	final REnvironmentVar env= this.searchEnvs.get(idx);
//				final RVector<RCharacterStore> ls= (RVector<RCharacterStore>) tools.evalData("ls(name=\""+item.getId()+"\", all.names=TRUE)", monitor);
//				final RCharacterStore lsData= ls.getData();
//				for (int i= 0; i < lsData.getLength(); i++) {
//					final String elementName= lsData.getChar(i);
////					final String elementName= lsData.getChar(133);
//					System.out.println(item.getId() + " " + elementName);
//					final RObject element= tools.evalStruct("as.environment(\""+item.getId()+"\")$\""+elementName+"\"", monitor);
//					System.out.println(element);
//				}
				
				// Regular code
				final RElementName elementName= env.getElementName();
				try {
//					long start= System.currentTimeMillis();
					final int loadOptions= RService.LOAD_PROMISE;
					final RObject robject= this.r.evalCombinedStruct(elementName,
							loadOptions, RService.DEPTH_INFINITE,
							m );
//					long end= System.currentTimeMillis();
//					System.out.println("update " + elementName.getDisplayName() + ": " + (end-start));
//					System.out.println(robject);
					if (robject != null && robject.getRObjectType() == RObject.TYPE_ENVIRONMENT) {
						final REnvironmentVar newEnv= (REnvironmentVar) robject;
						this.searchEnvs.set(idx, newEnv);
						updateEnvs.add(newEnv);
						continue;
					}
				}
				catch (final StatusException e) {
					RConsoleCorePlugin.logError("Error update environment "+ elementName, e);
					if (this.r.getTool().isTerminated() || m.isCanceled()) {
						throw e;
					}
				}
				env.setError("update error");
				updateEnvs.add(env);
				
//				final RObject test= tools.evalStruct("yy", monitor);
//				System.out.println(test);
			}
		}
		return updateEnvs;
	}
	
	private RObjectDB.NamespaceEntry getNamespaceEntry(final String name) {
		RObjectDB.NamespaceEntry entry= this.namespaceMap.get(name);
		if (entry == null) {
			entry= new NamespaceEntry();
			this.namespaceMap.put(name, entry);
		}
		return entry;
	}
	
	private String getPkgName(final REnvironmentVar env) {
		switch (env.getSpecialType()) {
		case REnvironment.ENVTYPE_BASE:
			return REnvironment.ENVNAME_BASE;
		case REnvironment.ENVTYPE_PACKAGE:
			return env.getEnvironmentName().substring(8);
		case REnvironment.ENVTYPE_NAMESPACE:
			return env.getEnvironmentName();
		case REnvironment.ENVTYPE_NAMESPACE_EXPORTS:
			return env.getEnvironmentName();
		default:
			return null;
		}
	}
	
	private EnvironmentEntry registerEnv(final Long handle, final REnvironmentVar env,
			final boolean isUptodate) {
		final EnvironmentEntry environmentEntry;
		if (handle != null) {
			environmentEntry= new EnvironmentEntry(env);
			this.envsMap.put(handle, environmentEntry);
		}
		else {
			environmentEntry= null;
		}
		
		final String name= getPkgName(env);
		if (name != null) {
			final RObjectDB.NamespaceEntry entry= getNamespaceEntry(name);
			switch (env.getSpecialType()) {
			case REnvironment.ENVTYPE_BASE:
			case REnvironment.ENVTYPE_PACKAGE:
				if (isUptodate || (entry.na == null && entry.packageEnv == null)) {
					entry.packageEnv= env;
				}
				break;
			case REnvironment.ENVTYPE_NAMESPACE:
				if (isUptodate || (entry.na == null && entry.namespaceEnv == null)) {
					entry.namespaceEnv= env;
				}
				break;
			case REnvironment.ENVTYPE_NAMESPACE_EXPORTS:
				if (isUptodate || (entry.na == null && entry.namespaceExports == null)) {
					entry.namespaceExports= env;
				}
				break;
			default:
				return environmentEntry;
			}
			
			if (isUptodate) {
				entry.na= null;
			}
		}
		return environmentEntry;
	}
	
	private void registerNA(final VirtualMissingVar na) {
		final RObjectDB.NamespaceEntry entry= getNamespaceEntry(na.getElementName().getSegmentName());
		entry.na= na;
		entry.namespaceEnv= null;
		entry.namespaceExports= null;
	}
	
	private void updateEnvMap(final List<REnvironmentVar> updateEnvs, final RObjectDB previous,
			final List<String> forcePkgNames,
			final ProgressMonitor m) throws StatusException {
		if (m.isCanceled()) {
			return;
		}
		this.previousDB= null;
		this.resolveMode= RECURSIVE;
		
		for (final REnvironmentVar env : this.searchEnvs) {
			registerEnv(Long.valueOf(env.getHandle()), env, true);
		}
		
		for (final REnvironmentVar env : updateEnvs) {
			final Long handle= Long.valueOf(env.getHandle());
			EnvironmentEntry entry= this.envsMap.get(handle);
			if (entry == null) {
				entry= registerEnv(handle, env, true);
			}
			check(entry, m);
		}
		this.previousDB= previous;
		this.forceUpdatePkgNames= forcePkgNames;
		for (final REnvironmentVar env : this.searchEnvs) {
			if (!updateEnvs.contains(env)) {
				check(env, m);
			}
		}
		this.previousDB= null;
		this.forceUpdatePkgNames= null;
		return;
	}
	
	public CombinedRElement resolve(final RReferenceVar ref, final int resolve,
			final int loadOptions,
			final ICombinedRDataAdapter r, final ProgressMonitor m) throws StatusException {
		this.r= r;
		this.resolveMode= toResolveMode(resolve);
		try {
			final CombinedRElement resolved= evalResolve(ref, ref.getElementName(),
					loadOptions, m );
			
			if (resolved != null) {
				checkDirectAccessName(resolved, ref.getElementName());
			}
			
			return resolved;
		}
		finally {
			this.r= null;
		}
	}
	
	private CombinedRElement evalResolve(final RReferenceVar ref, final RElementName fullName,
			int loadOptions,
			final ProgressMonitor m) throws StatusException {
		Long handle= (ref.getHandle() != 0) ? Long.valueOf(ref.getHandle()) : null;
		final byte mode= this.resolveMode;
		
		try {
			this.resolveMode= ((mode & RECURSIVE_UPTODATE) != 0) ? mode : (byte) (mode & ~UPTODATE);
			boolean lazy= false;
			if (ref.getReferencedRObjectType() == RObject.TYPE_ENVIRONMENT && handle != null) {
				ref.setResolver(this.workspace);
				
				{	final EnvironmentEntry entry= this.envsMap.get(handle);
					if (entry != null) {
						if ((mode & UPTODATE) == 0
								|| entry.env.getStamp() == this.r.getChangeStamp() ) {
							check(entry, m);
							return entry.env;
						}
						// we are about to replace an environment because of wrong stamp
						// to be save, resolve all (for object browser), but correct stamp
						// can be loaded later (like this request)
						this.resolveMode|= RECURSIVE;
					}
				}
				
				lazy= this.lazyEnvs.contains(handle);
				if (!lazy && this.previousDB != null) {
					final EnvironmentEntry prevEntry= this.previousDB.envsMap.get(handle);
					final List<String> forcePkgNames= this.forceUpdatePkgNames;
					final String pkgName;
					if (prevEntry != null
							&& ((mode & UPTODATE) == 0
									|| (prevEntry.env.getStamp() == this.r.getChangeStamp()))
							&& (forcePkgNames == null || (pkgName= getPkgName(prevEntry.env)) == null
									|| !forcePkgNames.contains(pkgName) )) {
						final EnvironmentEntry entry= registerEnv(handle, prevEntry.env, false);
						if (entry != null) {
							check(entry, m);
							return entry.env;
						}
					}
				}
			}
			
			CombinedRElement element= null;
			if (ref.getReferencedRObjectType() == RObject.TYPE_ENVIRONMENT && handle != null) {
				if (!(lazy || isNamespaceEnv(ref.getElementName()) )) {
					loadOptions|= RService.LOAD_PROMISE;
				}
				element= this.r.evalCombinedStruct(ref,
						loadOptions, RService.DEPTH_INFINITE, null, m );
			}
			else if (fullName != null) {
				if (!(lazy || isNamespaceEnv(fullName) )) {
					loadOptions|= RService.LOAD_PROMISE;
				}
				final RElementName symbolName= fullName.getLastSegment();
				if (symbolName.getType() == RElementName.MAIN_DEFAULT) {
					final RElementName envName= RElementName.create(fullName, symbolName, true);
					try {
						element= this.r.findCombinedStruct(symbolName, envName, false,
								loadOptions, RService.DEPTH_INFINITE, m );
					}
					catch (final StatusException e) {
					}
				}
				if (element == null) {
					element= this.r.evalCombinedStruct(fullName,
							loadOptions, RService.DEPTH_INFINITE, m );
				}
			}
			else {
				throw new StatusException(new ErrorStatus(RConsoleCorePlugin.BUNDLE_ID,
						"Unsupported ref: " + ref ));
			}
			if (element != null && element.getRObjectType() == RObject.TYPE_ENVIRONMENT) {
				final REnvironmentVar env= (REnvironmentVar) element;
				if (handle == null && env.getHandle() != 0) {
					handle= Long.valueOf(env.getHandle());
				}
				final EnvironmentEntry entry= registerEnv(handle, env, true);
				if (entry != null) {
					check(entry, m);
					return env;
				}
			}
			if (element instanceof CombinedRList) {
				check((CombinedRList) element, m);
			}
			return element;
		}
		catch (final StatusException e) {
			if (fullName != null 
					&&fullName.getNextSegment() == null
					&& RElementName.isPackageFacetScopeType(fullName.getType()) ) {
				final VirtualMissingVar na= new VirtualMissingVar(fullName,
						this.r.getTool(), this.r.getChangeStamp());
				registerNA(na);
			}
			
			RConsoleCorePlugin.logError("Error update ref: " + ref.getElementName(), e);
			if (this.r.getTool().isTerminated() || m.isCanceled()) {
				throw e;
			}
			return null;
		}
		finally {
			this.resolveMode= mode;
		}
	}
	
	private void checkDirectAccessName(final CombinedRElement var, final RElementName name) {
		if (name == null || name.getNextSegment() != null) {
			return;
		}
		
		if (var instanceof REnvironmentVar && RElementName.isScopeType(name.getType())) {
			((REnvironmentVar) var).setElementName(name);
		}
	}
	
	private void check(final EnvironmentEntry entry,
			final ProgressMonitor m) throws StatusException {
		final byte mode= (byte) (UPTODATE | this.resolveMode); // UPTODATE -> check to setResolver
		if ((mode & ~(entry.checked | entry.checking)) != 0) {
			final byte was= entry.checking;
			entry.checking|= mode;
			try {
				check(entry.env, m);
				entry.checked|= mode;
			}
			finally {
				entry.checking= was;
			}
		}
	}
	
	private void check(final CombinedRList list,
			final ProgressMonitor m) throws StatusException {
		if (list.hasModelChildren(null)) {
			final long length= list.getLength();
			if (length <= Integer.MAX_VALUE) {
				final int l= (int) length;
				ITER_CHILDREN : for (int i= 0; i < l; i++) {
					final RObject object= list.get(i);
					if (object != null) {
						switch (object.getRObjectType()) {
						case RObject.TYPE_REFERENCE:
							if ((this.resolveMode & RECURSIVE) != 0
									&& ((RReference) object).getReferencedRObjectType() == RObject.TYPE_ENVIRONMENT) {
								evalResolve((RReferenceVar) object, null, 0, m);
							}
							else {
								((RReferenceVar) object).setResolver(this.workspace);
							}
							continue ITER_CHILDREN;
						case RObject.TYPE_LIST:
						case RObject.TYPE_S4OBJECT:
							check((CombinedRList) object, m);
							continue ITER_CHILDREN;
						default:
							continue ITER_CHILDREN;
						}
					}
				}
			}
			else {
				ITER_CHILDREN : for (long i= 0; i < length; i++) {
					final RObject object= list.get(i);
					if (object != null) {
						switch (object.getRObjectType()) {
						case RObject.TYPE_REFERENCE:
							if ((this.resolveMode & RECURSIVE) != 0
									&& ((RReference) object).getReferencedRObjectType() == RObject.TYPE_ENVIRONMENT) {
								evalResolve((RReferenceVar) object, null, 0, m);
							}
							else {
								((RReferenceVar) object).setResolver(this.workspace);
							}
							continue ITER_CHILDREN;
						case RObject.TYPE_LIST:
						case RObject.TYPE_S4OBJECT:
							check((CombinedRList) object, m);
							continue ITER_CHILDREN;
						default:
							continue ITER_CHILDREN;
						}
					}
				}
			}
		}
	}
	
	public void handleRPkgChange(final List<String> names) {
		this.forceUpdatePkgNames= (this.forceUpdatePkgNames != null) ?
				ImCollections.concatList(this.forceUpdatePkgNames, names) :
				names;
	}
	
}
