/*=============================================================================#
 # Copyright (c) 2017, 2020 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.rj.server.rh;

import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;

import static org.eclipse.statet.rj.server.dbg.Srcfiles.equalsTimestamp;
import static org.eclipse.statet.rj.server.dbg.Tracepoints.LOGGER;
import static org.eclipse.statet.rj.server.dbg.Tracepoints.containsPositionsById;
import static org.eclipse.statet.rj.server.dbg.Tracepoints.equalsPositions;
import static org.eclipse.statet.rj.server.dbg.Tracepoints.filterPositionsById;
import static org.eclipse.statet.rj.server.dbg.Tracepoints.filterPositionsByIdRequired;
import static org.eclipse.statet.rj.server.dbg.Tracepoints.findIndexByReference;
import static org.eclipse.statet.rj.server.dbg.Tracepoints.findIndexBySrcref;
import static org.eclipse.statet.rj.server.dbg.Tracepoints.getSrcrefForIndex;
import static org.eclipse.statet.rj.server.dbg.Tracepoints.indexOfTracepointById;
import static org.eclipse.statet.rj.server.dbg.Tracepoints.rebasePositionsByIndex;
import static org.eclipse.statet.rj.server.rh.ObjectManager.WEAK_REF;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.LogRecord;

import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet;
import org.eclipse.statet.jcommons.collections.IdentitySet;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.collections.SortedArraySet;
import org.eclipse.statet.jcommons.lang.NonNull;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.lang.ObjectUtils;

import org.eclipse.statet.rj.server.RjsException;
import org.eclipse.statet.rj.server.RjsStatus;
import org.eclipse.statet.rj.server.dbg.DbgListener;
import org.eclipse.statet.rj.server.dbg.ElementTracepointInstallationRequest;
import org.eclipse.statet.rj.server.dbg.ElementTracepoints;
import org.eclipse.statet.rj.server.dbg.FlagTracepointInstallationRequest;
import org.eclipse.statet.rj.server.dbg.SrcfileData;
import org.eclipse.statet.rj.server.dbg.Srcref;
import org.eclipse.statet.rj.server.dbg.Tracepoint;
import org.eclipse.statet.rj.server.dbg.TracepointEvent;
import org.eclipse.statet.rj.server.dbg.TracepointPosition;
import org.eclipse.statet.rj.server.dbg.TracepointState;
import org.eclipse.statet.rj.server.dbg.TracepointStatesUpdate;
import org.eclipse.statet.rj.server.dbg.Tracepoints;
import org.eclipse.statet.rj.server.rh.ObjectManager.EnvListener;


@NonNullByDefault
public abstract class AbstractTracepointManager {
	
	
	protected static final String TOPLEVEL_ELEMENT_ID= "200:"; //$NON-NLS-1$
	
	private static final String ENV_INSTALLED_TAG= "#" + WEAK_REF + ":dbg.tracepoints";
	
	
	private static final int MAX_HISTORY= 12;
	private static final int MAX_FUZZY= 8;
	
	
	protected static final class StateSet extends SortedArraySet<@NonNull StateEntry> {
		
		
		public StateSet(final int initialSize) {
			super(new @NonNull StateEntry[initialSize], 0, null);
		}
		
		
		protected static final int binarySearchId(final StateEntry[] a, int begin, int end, final long id) {
			end--;
			while (begin <= end) {
				final int i= (begin + end) >>> 1;
				final int d= a[i].compareToId(id);
				if (d < 0) {
					begin= i + 1;
				}
				else if (d > 0) {
					end= i - 1;
				}
				else {
					return i;
				}
			}
			return -(begin + 1);
		}
		
		public int indexOfId(final long id) {
			return binarySearchId(array(), 0, size(), id);
		}
		
	}
	
	
	private static final boolean containsCommonElement(final List<? extends ElementTracepoints> list) {
		for (final ElementTracepoints element : list) {
			if (!element.getElementId().equals(TOPLEVEL_ELEMENT_ID)) {
				return true;
			}
		}
		return false;
	}
	
	private static final int indexOfStateEntry(final List<StateEntry> entries,
			final long id) {
		for (int idx= 0; idx < entries.size(); idx++) {
			if (entries.get(idx).getId() == id) {
				return idx;
			}
		}
		return -1;
	}
	
	protected static final @Nullable StateEntry getBreakpointState(final StateSet states,
			final long id) {
		final int idx= states.indexOfId(id);
		if (idx >= 0) {
			final StateEntry entry= states.get(idx);
			final TracepointState state= entry.getState();
			if (state != null
					&& (state.getType() & Tracepoint.TYPE_BREAKPOINT) != 0) {
				return entry;
			}
		}
		return null;
	}
	
	protected static final @Nullable StateEntry getBreakpointState(final StateSet states,
			final @Nullable String elementId, final int @Nullable [] index) {
		if (elementId != null && index != null) {
			for (int i= 0; i < states.size(); i++) {
				final StateEntry entry= states.get(i);
				final TracepointState state= entry.getState();
				if (state != null
						&& (state.getType() & Tracepoint.TYPE_BREAKPOINT) != 0
						&& elementId.equals(state.getElementId())
						&& Arrays.equals(index, state.getIndex()) ) {
					return entry;
				}
			}
		}
		return null;
	}
	
	private static final boolean isAllDeleted(final List<? extends TracepointPosition> positions,
			final StateSet states) {
		return false;
//		synchronized (states) {
//			for (final TracepointPosition position : positions) {
//				final int idx= states.indexOfId(position.getId());
//				if (idx >= 0 && states.get(idx).getState() != null) {
//					return false;
//				}
//			}
//		}
//		return true;
	}
	
	
	protected static final ImList<TracepointPosition> NO_POSITIONS= ImCollections.emptyList();
	protected static final ElementTracepoints NO_POSITION_ELEMENT_TRACEPOINTS= new ElementTracepoints(
			new SrcfileData(null, null, 0), "", null, NO_POSITIONS ); //$NON-NLS-1$
	protected static final ElementTracepoints NO_CHANGE_ELEMENT_TRACEPOINTS= new ElementTracepoints(
			new SrcfileData(null, null, 0), "", null, NO_POSITIONS ); //$NON-NLS-1$
	
	
	/**
	 * Collection of (best matching) element tracepoints for current tracepoint positions.
	 */
	protected final static class ElementTracepointsCollection {
		
		
		private final long updatingStamp;
		
		private final ElementTracepoints current;
		
		private final List<ElementTracepoints> list;
		
		private final long requestedTimestamp;
		
		
		public ElementTracepointsCollection(final long updatingStamp,
				final ElementTracepoints current, final List<ElementTracepoints> list,
				final long requestedTimestamp) {
			this.updatingStamp= updatingStamp;
			this.current= current;
			this.list= list;
			this.requestedTimestamp= requestedTimestamp;
		}
		
		public ElementTracepointsCollection(final long updatingStamp,
				final ElementTracepoints current, final ElementTracepoints single,
				final long requestedTimestamp) {
			this.updatingStamp= updatingStamp;
			this.current= current;
			this.list= ImCollections.newList(single);
			this.requestedTimestamp= requestedTimestamp;
		}
		
		
		public long getUpdatingStamp() {
			return this.updatingStamp;
		}
		
		public ElementTracepoints getCurrent() {
			return this.current;
		}
		
		public List<ElementTracepoints> getList() {
			return this.list;
		}
		
		public boolean isActualPositionsEmpty() {
			return this.current.getPositions().isEmpty();
		}
		
		public List<? extends TracepointPosition> getActualPositions(final List<? extends TracepointPosition> positions) {
			return filterPositionsByIdRequired(positions, this.current.getPositions());
		}
		
		public long getRequestedTimestamp() {
			return this.requestedTimestamp;
		}
		
	}
	
	
	protected static class PathEntry {
		
		
		private final String path;
		
		private long updateStamp;
		private @Nullable SrcfileData srcfile;
		
		private final List<ElementEntry> elementEntries= new ArrayList<>();
		
		private final StateSet states= new StateSet(8);
		
		private final List<ElementTracepointsCollection> updatingInstalled= new ArrayList<>();
		
		
		public PathEntry(final String path) {
			this.path= path;
		}
		
		
		public final String getPath() {
			return this.path;
		}
		
		public final long getUpdateStamp() {
			return this.updateStamp;
		}
		
		private int indexOf(final String id) {
			int low= 0;
			int high= this.elementEntries.size() - 1;
			while (low <= high) {
				final int mid= (low + high) >>> 1;
				final int diff= this.elementEntries.get(mid).id.compareTo(id);
				if (diff < 0) {
					low= mid + 1;
				}
				else if (diff > 0) {
					high= mid - 1;
				}
				else {
					return mid;
				}
			}
			return -(low + 1);
		}
		
		private ElementEntry ensureElement(final String id) {
			final int idx= indexOf(id);
			if (idx >= 0) {
				return this.elementEntries.get(idx);
			}
			else {
				final ElementEntry entry= new ElementEntry(id);
				this.elementEntries.add(-(idx + 1), entry);
				return entry;
			}
		}
		
		/** Adds or updates current positions */
		private void addTracepoints(final ElementTracepoints tracepoints, final long updateStamp) {
			synchronized (this.elementEntries) {
				this.updateStamp= updateStamp;
				this.srcfile= tracepoints.getSrcfile();
				
				final ElementEntry elementEntry= ensureElement(
						(tracepoints.getElementId().startsWith(TOPLEVEL_ELEMENT_ID)) ?
								TOPLEVEL_ELEMENT_ID : tracepoints.getElementId() );
				elementEntry.setTracepoints(tracepoints, updateStamp);
			}
		}
		
		public @Nullable ElementEntry getElementEntry(final String id) {
			synchronized (this.elementEntries) {
				final int idx= indexOf(id);
				return (idx >= 0) ? this.elementEntries.get(idx) : null;
			}
		}
		
		public @Nullable ElementTracepoints findElementTracepoints(
				final @Nullable String id, final long timestamp) {
			if (id == null) {
				return null;
			}
			final ElementEntry elementEntry= getElementEntry(id);
			return (elementEntry != null) ?
					elementEntry.findTracepoints(timestamp, this.states) :
					null;
		}
		
		/**
		 * Returns list with single CurrentPositionCollection for current tracepoint positions.
		 * @param timestamp timestamp of srcfile or <code>0</code>
		 * @param srcref srcref of element to match or <code>null</code>
		 * @return list with CurrentPositionCollection or <code>null</code>
		 */
		public @Nullable ElementTracepointsCollection findCurrentElementTracepoints(
				final @Nullable String id, final long timestamp, final int @Nullable [] srcref) {
			if (id == null && srcref == null) {
				return null;
			}
			
			ElementEntry elementEntry= null;
			boolean isNestedMatch= false;
			if (id != null) { // by id
				elementEntry= getElementEntry(id);
			}
			else if (timestamp != 0) { // by timestamp
				synchronized (this.elementEntries) {
					for (final ElementEntry entry : this.elementEntries) {
						if (entry.getId() == TOPLEVEL_ELEMENT_ID) {
							continue;
						}
						final ElementTracepoints cand= entry.getTracepoints(timestamp);
						if (cand != null && cand.getElementSrcref() != null
								&& Srcref.contains(cand.getElementSrcref(), srcref) ) {
							if (Srcref.equalsStart(cand.getElementSrcref(), srcref)) {
								elementEntry= entry;
								isNestedMatch= false;
								break;
							}
							else {
								elementEntry= entry;
								isNestedMatch= true;
							}
						}
					}
				}
			}
			else {
				synchronized (this.elementEntries) {
					ElementTracepoints best= null;
					boolean requireDim= false;
					for (final ElementEntry entry : this.elementEntries) {
						if (entry.getId() == TOPLEVEL_ELEMENT_ID) {
							continue;
						}
						final ElementTracepoints cand= entry.getCurrentTracepoints();
						if (cand != null && cand.getElementSrcref() != null
								&& Srcref.equalsStart(cand.getElementSrcref(), srcref)
								&& !isAllDeleted(cand.getPositions(), this.states) ) {
							if (Srcref.equalsDim(cand.getElementSrcref(), srcref)) {
								if (!requireDim) {
									requireDim= true;
									best= null;
								}
							}
							else {
								if (requireDim) {
									continue;
								}
							}
							if (best == null || entry.getUpdateStamp() > elementEntry.getUpdateStamp()) {
								elementEntry= entry;
								best= cand;
							}
						}
					}
					if (requireDim && best != null) {
						return new ElementTracepointsCollection(elementEntry.getUpdateStamp(),
								best, best, timestamp );
					}
				}
			}
			return (elementEntry != null) ?
					(isNestedMatch) ?
							elementEntry.findCurrentNestedTracepoints(timestamp, srcref, this.states) :
							elementEntry.findCurrentTracepoints(timestamp, srcref, this.states) :
					null;
		}
		
		
		/** Returns the list with current states. Synchronization required! */
		public StateSet getStates() {
			return this.states;
		}
		
		public @Nullable StateEntry getBreakpointState(final long id) {
			synchronized (this.states) {
				return AbstractTracepointManager.getBreakpointState(this.states, id);
			}
		}
		
		
		public void addInstalled(final ElementTracepointsCollection collection) {
			this.updatingInstalled.add(collection);
		}
		
		private void finishUpdatingInst(final RhEnv env, final boolean clear,
				final StateSet installed, final StateSet changed) {
			synchronized (this.states) {
				for (int i= 0; i < this.states.size(); i++) {
					final StateEntry stateEntry= this.states.get(i);
					int isInstalled= 0;
					boolean isUpdated= false;
					for (int j= 0; j < this.updatingInstalled.size(); j++) {
						final ElementTracepointsCollection collection= this.updatingInstalled.get(j);
						if (indexOfTracepointById(collection.getCurrent().getPositions(), stateEntry.getId()) >= 0) {
							isInstalled++;
							isUpdated|= stateEntry.addUpdatingInstElement(collection);
						}
					}
					
					if (isInstalled > 0) {
						if (!stateEntry.instEnvs.contains(env) && stateEntry.instEnvs.add(env)) {
							changed.add(stateEntry);
							if (LOGGER.isLoggable(Level.FINE)) {
								LOGGER.log(Level.FINE,
										"[TP] Updating element tracepoint {0}: installed in {2} element(s) of {1} now.",
										new Object[] {
												stateEntry,
												env,
												(clear) ? isInstalled : "one or more" } );
							}
						}
						else if (isUpdated) {
							changed.add(stateEntry);
						}
						installed.add(stateEntry);
					}
					else if (clear) {
						if (stateEntry.instEnvs.remove(env)) {
							if (stateEntry.instEnvs.isEmpty()) {
								changed.add(stateEntry);
							}
							if (LOGGER.isLoggable(Level.FINE)) {
								LOGGER.log(Level.FINE,
										"[TP] Updating element tracepoint {0}: installed in NO element of {1} now.",
										new Object[] {
												stateEntry,
												env } );
							}
						}
					}
				}
			}
			
			this.updatingInstalled.clear();
		}
		
	}
	
	protected static class ElementEntry {
		
		
		private final String id;
		
		private final List<ElementTracepoints> history= new ArrayList<>();
		
		private long updateStamp;
		
		
		public ElementEntry(final String id) {
			this.id= id;
		}
		
		
		public final String getId() {
			return this.id;
		}
		
		
		/** Sets current element tracepoints */
		protected void setTracepoints(final ElementTracepoints tracepoints, final long updateStamp) {
			this.updateStamp= updateStamp;
			if (this.history.isEmpty()) {
				this.history.add(tracepoints);
			}
			else if (this.history.get(0).getSrcfile().getTimestamp() == tracepoints.getSrcfile().getTimestamp()) {
				this.history.set(0, tracepoints);
			}
			else {
				if (this.history.size() >= MAX_HISTORY) {
					this.history.remove(this.history.size() - 1);
				}
				this.history.add(0, tracepoints);
			}
		}
		
		public long getUpdateStamp() {
			return this.updateStamp;
		}
		
		/** Returns current element tracepoints */
		public @Nullable ElementTracepoints getCurrentTracepoints() {
			synchronized (this.history) {
				return (!this.history.isEmpty()) ? this.history.get(0) : null;
			}
		}
		
		/** Returns positions for specified timestamp */
		public @Nullable ElementTracepoints getTracepoints(final long timestamp) {
			synchronized (this.history) {
				if (!this.history.isEmpty()) {
					if (timestamp != 0) {
						for (int i= 0; i < this.history.size(); i++) {
							final ElementTracepoints cand= this.history.get(i);
							if (equalsTimestamp(cand.getSrcfile().getTimestamp(), timestamp)) {
								return cand;
							}
						}
					}
				}
				return null;
			}
		}
		
		public @Nullable ElementTracepoints findTracepoints(
				final long timestamp,
				final @Nullable StateSet states) {
			synchronized (this.history) {
				if (!this.history.isEmpty()) {
					final ElementTracepoints current= this.history.get(0);
					int end= this.history.size();
					if (states != null && !current.getPositions().isEmpty()
							&& isAllDeleted(current.getPositions(), states) ) {
						return NO_POSITION_ELEMENT_TRACEPOINTS;
					}
					if (end > 1 && !current.getPositions().isEmpty()) {
						ElementTracepoints best= null;
						List<TracepointPosition> timestampPositions= null;
						if (timestamp != 0) {
							for (int i= 0; i < end; i++) {
								final ElementTracepoints cand= this.history.get(i);
								if (equalsTimestamp(cand.getSrcfile().getTimestamp(), timestamp)) {
									if (containsPositionsById(cand.getPositions(), current.getPositions())) {
										return cand;
									}
									best= cand;
									timestampPositions= filterPositionsById(cand.getPositions(), current.getPositions());
									end= i;
									break;
								}
							}
							if (timestampPositions != null && !timestampPositions.isEmpty() ) {
								for (int i= 0; i < end; i++) {
									final ElementTracepoints cand= this.history.get(i);
									if (equalsPositions(cand.getPositions(), timestampPositions,
											timestampPositions )) {
										return cand;
									}
								}
							}
						}
						if (best != null) {
							return best;
						}
					}
					return current;
				}
				return null;
			}
		}
		
		/** Returns CurrentPositionCollection with current tracepoints positions */
		public @Nullable ElementTracepointsCollection findCurrentTracepoints(
				final long timestamp, final int @Nullable [] srcref,
				final @Nullable StateSet states) {
			synchronized (this.history) {
				if (!this.history.isEmpty()) {
					final ElementTracepoints current= this.history.get(0);
					int end= this.history.size();
					if (states != null && !current.getPositions().isEmpty()
							&& isAllDeleted(current.getPositions(), states) ) {
						return new ElementTracepointsCollection(this.updateStamp,
								NO_POSITION_ELEMENT_TRACEPOINTS, NO_POSITION_ELEMENT_TRACEPOINTS, 0 );
					}
					if (end > 1 && !current.getPositions().isEmpty()) {
						if (timestamp != 0) {
							List<TracepointPosition> timestampActualPositions= null;
							for (int i= 0; i < end; i++) {
								final ElementTracepoints cand= this.history.get(i);
								if (equalsTimestamp(cand.getSrcfile().getTimestamp(), timestamp)) {
									if (containsPositionsById(cand.getPositions(), current.getPositions())) {
										return new ElementTracepointsCollection(this.updateStamp,
												current, cand, timestamp );
									}
									timestampActualPositions= filterPositionsById(cand.getPositions(), current.getPositions());
									end= i;
									break;
								}
							}
							if (timestampActualPositions != null && !timestampActualPositions.isEmpty()) {
								for (int i= 0; i < end; i++) {
									final ElementTracepoints cand= this.history.get(i);
									if (containsPositionsById(cand.getPositions(), current.getPositions())
											&& equalsPositions(cand.getPositions(), timestampActualPositions,
														timestampActualPositions )) {
										return new ElementTracepointsCollection(this.updateStamp,
												current, cand, timestamp );
									}
								}
							}
						}
						if (srcref != null) {
							final List<ElementTracepoints> selected= new ArrayList<>(MAX_FUZZY);
							selected.add(current);
							for (int i= 1; i < end && selected.size() < MAX_FUZZY; i++) {
								final ElementTracepoints cand= this.history.get(i);
								if (cand.getElementSrcref() != null
										&& Srcref.equalsDim(cand.getElementSrcref(), srcref)
										&& containsPositionsById(cand.getPositions(), current.getPositions())
										&& !equalsPositions(cand.getPositions(),
												selected.get(selected.size() - 1).getPositions(),
												current.getPositions() )) {
									selected.add(cand);
								}
							}
							return new ElementTracepointsCollection(this.updateStamp,
									current, selected, timestamp );
						}
					}
					return new ElementTracepointsCollection(this.updateStamp,
							current, current, timestamp );
				}
				return null;
			}
		}
		
		public @Nullable ElementTracepointsCollection findCurrentNestedTracepoints(
				final long timestamp, final int[] srcref,
				final @Nullable StateSet states) {
			synchronized (this.history) {
				if (!this.history.isEmpty()) {
					final ElementTracepoints current= this.history.get(0);
					int end= this.history.size();
					if (current.getPositions().isEmpty()
							|| (states != null && isAllDeleted(current.getPositions(), states)) ) {
						return createNoPositionCollection();
					}
					if (timestamp != 0) {
						int[] timestampSrcref= null;
						List<TracepointPosition> timestampPositions= null;
						for (int i= 0; i < end; i++) {
							final ElementTracepoints cand= this.history.get(i);
							if (equalsTimestamp(cand.getSrcfile().getTimestamp(), timestamp)) {
								if (cand.getElementSrcref() == null) {
									break;
								}
								final int[] index= findIndexBySrcref(cand.getPositions(),
										nonNullAssert(cand.getElementSrcref()), srcref );
								if (index != null) {
									timestampSrcref= nonNullAssert(getSrcrefForIndex(
											cand.getPositions(), index ));
									timestampPositions= rebasePositionsByIndex(
											cand.getPositions(), index );
									if (containsPositionsById(cand.getPositions(), current.getPositions())) {
										return createNestedCollection(current,
												createNested(cand, timestampSrcref, filterPositionsById(
														timestampPositions, current.getPositions() )),
												timestamp, states );
									}
								}
								end= i;
								break;
							}
						}
						if (timestampPositions != null && !timestampPositions.isEmpty()) {
							for (int i= 0; i < end; i++) {
								final ElementTracepoints cand= this.history.get(i);
								if (containsPositionsById(cand.getPositions(), current.getPositions())) {
									final List<TracepointPosition> compareList= filterPositionsById(
											cand.getPositions(), timestampPositions );
									final int[] index= findIndexByReference(compareList, timestampPositions);
									if (index != null) {
										final int[] candSrcref= nonNullAssert(getSrcrefForIndex(
												compareList, index ));
										final List<TracepointPosition> candPositions= rebasePositionsByIndex(
												cand.getPositions(), index );
										if (equalsPositions(candPositions, timestampPositions,
												timestampPositions )) {
											return createNestedCollection(current,
													createNested(cand, candSrcref, filterPositionsById(
															candPositions, current.getPositions() )),
													timestamp, states );
										}
									}
								}
							}
							{	final List<TracepointPosition> positions= filterPositionsById(
										timestampPositions, current.getPositions() );
								if (positions.isEmpty()
										|| (states != null && isAllDeleted(positions, states)) ) {
									return createNoPositionCollection();
								}
							}
						}
						return createNoChangeCollection();
					}
				}
				return null;
			}
		}
		
		private ElementTracepointsCollection createNoPositionCollection() {
			return new ElementTracepointsCollection(this.updateStamp,
					NO_POSITION_ELEMENT_TRACEPOINTS, NO_POSITION_ELEMENT_TRACEPOINTS, 0 );
		}
		
		private ElementTracepointsCollection createNoChangeCollection() {
			return new ElementTracepointsCollection(this.updateStamp,
					NO_CHANGE_ELEMENT_TRACEPOINTS, NO_CHANGE_ELEMENT_TRACEPOINTS, 0 );
		}
		
		private ElementTracepoints createNested(final ElementTracepoints cand,
				final int[] srcref, final List<TracepointPosition> nestedPositions) {
			return new ElementTracepoints(cand.getSrcfile(), this.id, srcref, nestedPositions);
		}
		
		private ElementTracepointsCollection createNestedCollection(final ElementTracepoints current,
				final ElementTracepoints nested, final long requestedTimestamp,
				final @Nullable StateSet states) {
			final List<TracepointPosition> currentPositions= filterPositionsById(
					current.getPositions(), nested.getPositions());
			if (currentPositions.isEmpty()
					|| (states != null && isAllDeleted(currentPositions, states)) ) {
				return createNoPositionCollection();
			}
			return new ElementTracepointsCollection(this.updateStamp,
					new ElementTracepoints(current.getSrcfile(), this.id, null, currentPositions),
					nested, requestedTimestamp );
		}
		
	}
	
	protected class StateEntry implements Comparable<StateEntry> {
		
		private final String path;
		private final long id;
		
		private final List<RhEnv> instEnvs= new ArrayList<>();
		private @Nullable ElementTracepoints instElement;
		private long instUpdatingStamp;
		
		private @Nullable ElementTracepointsCollection updatingInstElement;
		
		private @Nullable TracepointState state;
		
		private @Nullable ParsedExpr parsedExpr;
		
		
		public StateEntry(final String path, final long id) {
			this.path= path;
			this.id= id;
		}
		
		
		public final long getId() {
			return this.id;
		}
		
		public final boolean isInstalled() {
			return !this.instEnvs.isEmpty();
		}
		
		public synchronized void setState(final TracepointState state) {
			this.state= state;
		}
		
		public synchronized final @Nullable TracepointState getState() {
			return this.state;
		}
		
		public synchronized ParsedExpr getParsedExpr(final String source) {
			ParsedExpr pe= this.parsedExpr;
			if (pe != null) {
				if (pe.getSource().equals(source)) {
					return pe;
				}
				AbstractTracepointManager.this.objManager.addToDispose(pe);
				this.parsedExpr= null;
			}
			pe= new ParsedExpr(source);
			if (this.state != null) {
				this.parsedExpr= pe;
			}
			return pe;
		}
		
		public synchronized void removed() {
			this.state= null;
			if (this.parsedExpr != null) {
				AbstractTracepointManager.this.objManager.addToDispose(this.parsedExpr);
				this.parsedExpr= null;
			}
		}
		
		
		private @Nullable TracepointEvent checkInstalled(final @Nullable ElementTracepoints prevElement) {
			final ElementTracepoints element= this.instElement;
			if (element != null && element != prevElement
					&& (prevElement == null
							|| !element.getElementId().equals(prevElement.getElementId()) )) {
				return new TracepointEvent(TracepointEvent.KIND_INSTALLED,
						0, element.getSrcfile().getPath(), this.id,
						element.getElementId(), null, 0 );
			}
			return null;
		}
		
		private @Nullable TracepointEvent checkUninstalled() {
			final ElementTracepoints element= this.instElement;
			if (element != null) {
				this.instElement= null;
				return new TracepointEvent(TracepointEvent.KIND_UNINSTALLED,
							0, element.getSrcfile().getPath(), this.id,
							element.getElementId(), null, 0 );
			}
			return null;
		}
		
		
		private boolean addUpdatingInstElement(final ElementTracepointsCollection collection) {
			if (this.updatingInstElement == null
					|| collection.getUpdatingStamp() > this.updatingInstElement.getUpdatingStamp()) {
				this.updatingInstElement= collection;
				return true;
			}
			return false;
		}
		
		private void finishUpdatingInst(final List<TracepointEvent> events) {
			TracepointEvent event= null;
			
			if (isInstalled()) {
				final ElementTracepoints prevElement= this.instElement;
				if (this.updatingInstElement != null
						&& (getClearUpdatingInst()
								|| this.instElement == null
								|| this.updatingInstElement.getUpdatingStamp() > this.instUpdatingStamp )) {
					this.instElement= this.updatingInstElement.getCurrent();
					this.instUpdatingStamp= this.updatingInstElement.getUpdatingStamp();
					event= checkInstalled(prevElement);
				}
			}
			else {
				event= checkUninstalled();
			}
			if (event != null) {
				events.add(event);
			}
			this.updatingInstElement= null;
		}
		
		private void removeInst(final RhEnv env, final List<TracepointEvent> events) {
			TracepointEvent event= null;
			if (isInstalled() && this.instEnvs.remove(env)
					&& this.instEnvs.isEmpty() ) {
				event= checkUninstalled();
			}
			if (event != null) {
				events.add(event);
			}
		}
		
		
		@Override
		public int compareTo(final StateEntry other) {
			return (this.id < other.id) ? -1 : (this.id != other.id) ? 1 :
					this.path.compareTo(other.path);
		}
		
		private int compareToId(final long otherId) {
			return (this.id < otherId) ? -1 : (this.id != otherId) ? 1 : 0;
		}
		
		@Override
		public final int hashCode() {
			return Long.hashCode(this.id);
		}
		
		@Override
		public final boolean equals(final @Nullable Object obj) {
			return (this == obj
					|| (obj instanceof StateEntry
							&& this.id == ((StateEntry) obj).id
							&& this.path.equals(((StateEntry) obj).path)) );
		}
		
		@Override
		public String toString() {
			final StringBuilder sb= new StringBuilder(16 + 6 + this.path.length());
			Tracepoints.append(this.id, sb);
			sb.append(" in '");
			sb.append(this.path);
			sb.append('\'');
			return sb.toString();
		}
		
	}
	
	
	protected final ObjectManager objManager;
	private final DbgListener listener;
	
	private final Map<String, PathEntry> pathMap= new HashMap<>(32);
	private @Nullable ImList<PathEntry> pathList;
	private final Object stateUpdate= new Object();
	private volatile boolean isAnyEnabled;
	
	private final IdentitySet<String> envTags= new CopyOnWriteIdentityListSet<>();
	
	private boolean isBreakpointsEnabled= true;
	
	private @Nullable RhEnv updatingEnv;
	private boolean updatingEnvComplete;
	private final StateSet updatingStates= new StateSet(32);
	
	
	public AbstractTracepointManager(final ObjectManager objManager, final DbgListener listener) {
		this.objManager= objManager;
		this.listener= listener;
		
		this.objManager.addEnvListener(new EnvListener() {
			@Override
			public void onEnvRemoved(final RhEnv env, final boolean finalized) {
				if (finalized && env.isReg(ENV_INSTALLED_TAG)) {
					updateInstOnRemoved(env);
				}
			}
		});
	}
	
	
	protected boolean isAnyTracepointEnabled() {
		return this.isAnyEnabled;
	}
	
	protected PathEntry ensurePathEntry(final String path) {
		synchronized (this.pathMap) {
			PathEntry entry= this.pathMap.get(path);
			if (entry == null) {
				entry= new PathEntry(path);
				this.pathMap.put(path, entry);
				this.pathList= null;
			}
			return entry;
		}
	}
	
	protected ImList<PathEntry> getPathEntries() {
		synchronized (this.pathMap) {
			ImList<PathEntry> pathList= this.pathList;
			if (pathList == null) {
				pathList= ImCollections.toList(this.pathMap.values());
				this.pathList= pathList;
			}
			return pathList;
		}
	}
	
	protected @Nullable PathEntry getPathEntry(final String path) {
		synchronized (this.pathMap) {
			return this.pathMap.get(path);
		}
	}
	
	protected @Nullable PathEntry findPathEntryByFileName(final String fileName) {
		synchronized (this.pathMap) {
			for (final PathEntry entry : this.pathMap.values()) {
				final SrcfileData srcfile= entry.srcfile;
				if (srcfile != null && fileName.equals(srcfile.getName())) {
					return entry;
				}
			}
			return null;
		}
	}
	
	private void addTracepoints(final ElementTracepoints tracepoints, final long updateStamp) {
		final SrcfileData srcfile= tracepoints.getSrcfile();
		final String srcfilePath= srcfile.getPath();
		if (srcfilePath != null) {
			final PathEntry entry= ensurePathEntry(srcfilePath);
			entry.addTracepoints(tracepoints, updateStamp);
		}
	}
	
	protected void addTracepoints(final List<? extends ElementTracepoints> tracepointsList) {
		final long updateStamp= System.nanoTime();
		for (final ElementTracepoints tracepoints : tracepointsList) {
			addTracepoints(tracepoints, updateStamp);
		}
	}
	
	/**
	 * Updates the state of the specified tracepoints
	 * 
	 * @param request the request with tracepoint state updates
	 * @param reset if all existing tracepoint state should be reset
	 * @return update result status
	 */
	public RjsStatus updateTracepointStates(final TracepointStatesUpdate request) {
		synchronized (this.stateUpdate) {
			final List<String> reset;
			if (request.getReset()) {
				synchronized (this.pathMap) {
					reset= new ArrayList<>(this.pathMap.keySet());
				}
			}
			else {
				reset= null;
			}
			
			boolean isAnyEnabled= false;
			
			final List<StateEntry> oldStateEntries= new ArrayList<>();
			final List<TracepointState> list= request.getStates();
			for (int i= 0; i < list.size(); ) {
				final String path= list.get(i).getFilePath();
				if (path == null) {
					i++;
					continue;
				}
				
				final PathEntry pathEntry= ensurePathEntry(path);
				synchronized (pathEntry.states) {
					if (reset != null && reset.remove(path) && !pathEntry.states.isEmpty()) {
						oldStateEntries.addAll(pathEntry.states);
						pathEntry.states.clear();
					}
					for (; i < list.size(); i++) {
						final TracepointState state= list.get(i);
						if (!path.equals(state.getFilePath())) {
							break;
						}
						
						final int idx= pathEntry.states.indexOfId(state.getId());
						StateEntry entry= null;
						if (idx >= 0) {
							entry= pathEntry.states.get(idx);
						}
						
						if (state.getType() != Tracepoint.TYPE_DELETED) {
							if (entry == null && reset != null) {
								final int oldIdx= indexOfStateEntry(oldStateEntries, state.getId());
								if (oldIdx >= 0) {
									entry= oldStateEntries.remove(oldIdx);
								}
							}
							if (entry == null) {
								entry= new StateEntry(path, state.getId());
							}
							entry.setState(state);
							if (idx < 0) {
								pathEntry.states.add(entry);
							}
							isAnyEnabled |= state.isEnabled();
						}
						else if (idx >= 0) {
							pathEntry.states.remove(idx);
							oldStateEntries.add(entry);
						}
					}
				}
				
				onRemoved(oldStateEntries);
				oldStateEntries.clear();
				
				if (reset != null) {
					this.isAnyEnabled= isAnyEnabled;
				}
			}
			if (reset != null) {
				for (final String path : reset) {
					final PathEntry entry= ensurePathEntry(path);
					if (!entry.states.isEmpty()) {
						synchronized (entry.states) {
							onRemoved(entry.states);
							entry.states.clear();
						}
					}
				}
			}
			return RjsStatus.OK_STATUS;
		}
	}
	
	private void onRemoved(final List<StateEntry> entries) {
		for (final StateEntry entry : entries) {
			entry.removed();
		}
	}
	
	
	/**
	 * Sets if breakpoints are globally enabled.
	 * 
	 * @param enabled
	 */
	public void setBreakpointsEnabled(final boolean enabled) {
		this.isBreakpointsEnabled= enabled;
	}
	
	/**
	 * Returns if breakpoints are globally enabled.
	 * 
	 * @return
	 */
	public final boolean isBreakpointsEnabled() {
		return this.isBreakpointsEnabled;
	}
	
	
	/**
	 * Registers the environment for tracepoint management.
	 * 
	 * @param key
	 * @param envHandle handle of the environment
	 * @param objectNames object names to update
	 */
	public void registerEnv(String key, final Handle envHandle,
			final @Nullable List<String> objectNames) {
		key= key.intern();
		this.envTags.add(key);
		final RhEnv env= this.objManager.registerEnv(envHandle, key);
		updateInst(env, objectNames);
		finishUpdatingInst();
	}
	
	/**
	 * Deletes registration of the environment for tracepoint management.
	 * 
	 * @param key
	 * @param envHandle handle of the environment
	 */
	public void unregisterEnv(final String key, final Handle envHandle) {
		this.objManager.unregisterEnv(envHandle, key.intern());
	}
	
	/**
	 * Deletes registration of the environment for tracepoint management.
	 */
	public void unregisterEnvs(final String key) {
		this.objManager.unregisterEnvs(key.intern());
	}
	
	protected void addEnvWithParents(final List<RhEnv> envs, final RhEnv env) throws RjsException {
		RhEnv env0= env;
		while (env0 != null && !envs.contains(env0)) {
			envs.add(env0);
			
			env0= this.objManager.getParentEnv(env0);
		}
	}
	
	
	public RjsStatus installTracepoints(final ElementTracepointInstallationRequest request)
			throws RjsException {
		final List<? extends ElementTracepoints> tracepointsList= request.getRequests();
		
		addTracepoints(tracepointsList);
		
		if (containsCommonElement(tracepointsList)) {
			updateInst();
		}
		
		return RjsStatus.OK_STATUS;
	}
	
	public RjsStatus installTracepoints(final FlagTracepointInstallationRequest request)
			throws RjsException {
		final byte[] types= request.getTypes();
		final int[] flags= request.getFlags();
		
		for (int i= 0; i < types.length; i++) {
			switch (types[i]) {
			case Tracepoint.TYPE_EB:
				performUpdatingInstEB(flags[i]);
				break;
			default:
				break;
			}
		}
		
		return RjsStatus.OK_STATUS;
	}
	
	public void updateInst() throws RjsException {
		try {
			this.objManager.update();
			final List<RhEnv> envs= new ArrayList<>(64);
			envs.addAll(this.objManager.getSearchPath());
			for (final RhEnv env : this.objManager.getStackFrames()) {
				addEnvWithParents(envs, env);
			}
			for (final RhEnv env: this.objManager.getEnvs()) {
				if ((env.isReg(ENV_INSTALLED_TAG) || env.isRegAny(this.envTags))
						&& !envs.contains(env) ) {
					envs.add(env);
				}
			}
			
			for (final RhEnv env : envs) {
				performUpdatingInst(env, null);
			}
		}
		finally {
			finishUpdatingInst();
		}
	}
	
	public void updateInst(final RhEnv env, final @Nullable List<String> objectNames) {
		try {
			performUpdatingInst(env, objectNames);
		}
		finally {
			finishUpdatingInst();
		}
	}
	
	
	protected abstract void performUpdatingInstEB(final int i);
	
	protected abstract void performUpdatingInst(final RhEnv env, final @Nullable List<String> objectNames);
	
	
	protected void notifyListeners(final List<TracepointEvent> events) {
		if (!events.isEmpty()) {
			this.listener.handle(events);
		}
	}
	
	protected void notifyListeners(final TracepointEvent event) {
		this.listener.handle(ImCollections.newList(event));
	}
	
	protected void beginUpdatingInstEnv(final RhEnv env, final @Nullable List<String> namesToUpdate) {
		this.updatingEnv= env;
		this.updatingEnvComplete= (namesToUpdate == null);
		
		if (LOGGER.isLoggable(Level.FINE)) {
			if (namesToUpdate != null) {
				LOGGER.log(Level.FINE,
						"[TP] Updating element tracpoints in selected element(s) of {0}..." +
								"\n\telementNames= {1}",
						new Object[] { env, namesToUpdate } ); // TODO encode names
			}
			else {
				LOGGER.log(Level.FINE,
						"[TP] Updating element tracpoints in all elements of {0}...",
						new Object[] { env } );
			}
		}
	}
	
	protected final boolean getClearUpdatingInst() {
		return this.updatingEnvComplete;
	}
	
	protected void finishUpdatingInstEnv() {
		final RhEnv env= this.updatingEnv;
		if (env != null) {
			try {
				final boolean clear= this.updatingEnvComplete;
				final StateSet prevInstalled= (StateSet) env.getData(ENV_INSTALLED_TAG);
				final StateSet installed= (clear || prevInstalled == null) ?
						new StateSet(0) : prevInstalled;
				
				final List<PathEntry> pathEntries= getPathEntries();
				for (final PathEntry entry : pathEntries) {
					entry.finishUpdatingInst(env, clear, installed, this.updatingStates);
				}
				
				if (!installed.isEmpty()) {
					if (installed != prevInstalled) {
						env.addReg(ENV_INSTALLED_TAG, installed);
					}
				}
				else {
					if (prevInstalled != null) {
						env.removeReg(ENV_INSTALLED_TAG);
					}
				}
			}
			catch (final Exception e) {
				final LogRecord record= new LogRecord(Level.SEVERE,
						"[TP] An error occured when updating tracepoint installation states for {0}." );
				record.setParameters(new Object[] { env });
				record.setThrown(e);
				LOGGER.log(record);
			}
			finally {
				this.updatingEnv= null;
			}
		}
	}
	
	protected void finishUpdatingInst() {
		if (!this.updatingStates.isEmpty()) {
			final List<TracepointEvent> events= new ArrayList<>();
			for (final StateEntry entry : this.updatingStates) {
				entry.finishUpdatingInst(events);
			}
			
			notifyListeners(events);
			
			this.updatingStates.clear();
		}
	}
	
	protected void updateInstOnRemoved(final RhEnv env) {
		final StateSet installed= ObjectUtils.nonNullAssert(
				(StateSet) env.getData(ENV_INSTALLED_TAG) );
		final List<TracepointEvent> events= new ArrayList<>();
		for (final StateEntry stateEntry : installed) {
			stateEntry.removeInst(env, events);
		}
		
		notifyListeners(events);
	}
	
}
