/*******************************************************************************
 * Copyright (c) 2018 Aston University.
 * 
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License, v. 2.0 are satisfied: GNU General Public License, version 3.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0
 *
 * Contributors:
 *     Antonio Garcia-Dominguez - initial API and implementation
 ******************************************************************************/
package org.eclipse.hawk.greycat;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import org.eclipse.hawk.core.graph.EmptyIGraphIterable;
import org.eclipse.hawk.core.graph.IGraphEdge;
import org.eclipse.hawk.core.graph.IGraphIterable;
import org.eclipse.hawk.core.graph.IGraphDatabase.Mode;
import org.eclipse.hawk.core.graph.timeaware.ITimeAwareGraphNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Iterators;

import greycat.Constants;
import greycat.Graph;
import greycat.Node;
import greycat.Type;
import greycat.plugin.NodeState;
import greycat.plugin.Resolver;
import greycat.struct.DoubleArray;
import greycat.struct.IntArray;
import greycat.struct.LongArray;
import greycat.struct.Relation;
import greycat.struct.StringArray;
import greycat.struct.StringIntMap;

public class GreycatNode implements ITimeAwareGraphNode {

	protected static class StreamIterable<T> implements Iterable<T> {
		private Stream<T> stream;

		protected StreamIterable(Stream<T> stream) {
			this.stream = stream;
		}

		@Override
		public Iterator<T> iterator() {
			return stream.iterator();
		}
	}

	private enum Direction {
		IN {
			@Override
			public String getPrefix() {
				return "in_";
			}

			public IGraphEdge convertToEdge(String type, GreycatNode current, GreycatNode other) {
				if (GreycatHeavyEdge.NODETYPE.equals(other.getNodeLabel())) {
					return new GreycatHeavyEdge(other, type);
				}
				return new GreycatLightEdge(other, current, type);
			}
		}, OUT {
			@Override
			public String getPrefix() {
				return "out_";
			}

			@Override
			public IGraphEdge convertToEdge(String type, GreycatNode current, GreycatNode other) {
				if (GreycatHeavyEdge.NODETYPE.equals(other.getNodeLabel())) {
					return new GreycatHeavyEdge(other, type);
				}
				return new GreycatLightEdge(current, other, type);
			}
		};

		public abstract String getPrefix();
		public abstract IGraphEdge convertToEdge(String type, GreycatNode current, GreycatNode other);
	}

	private final class NodeProvider {
		private Graph _graph;
		private Node _node;

		public NodeProvider(Graph graph, Node node) {
			this._graph = graph;
			this._node = node;
		}

		public Node get() {
			if (db.getGraph() == _graph) {
				return _node;
			} else {
				// graph in DB changed: need to free and refetch the node
				_node.free();

				CompletableFuture<Node> result = new CompletableFuture<>();
				db.getGraph().lookup(world, time, id, node -> result.complete(node));
				try {
					_node = result.get();
					_graph = db.getGraph();
				} catch (InterruptedException | ExecutionException e) {
					LOGGER.error(String.format("Could not refetch node %d:%d:%d", world, time, id), e);
				}

				return _node;
			}
		}

		public void markDirty() {
			db.markDirty(GreycatNode.this);
		}

		public void free() {
			if (_node != null) {
				_node.free();
				_node = null;
				_graph = null;
			}
		}
	}

	/**
	 * Encapsulates an access to the underlying node, with implicit free unless
	 * changed since the last save, and implicit saves upon full closing of all
	 * nodes open so far. Allows for nested calls: should be safe as long as we
	 * stick to try-with-resources.
	 */
	private int nestingLevel = 0;
	protected final class NodeReader implements AutoCloseable, Supplier<Node> {
		private NodeReader() {
			++nestingLevel;
			db.markOpen(GreycatNode.this);
		}

		public Node get() {
			return nodeProvider.get();
		}

		public void markDirty() {
			nodeProvider.markDirty();
		}

		@Override
		public void close() {
			if (--nestingLevel <= 0) {
				db.markClosed(GreycatNode.this);
			}
		}
	}

	/** Prefix for all attribute names. Prevents clashes with reserved names. */
	private static final String ATTRIBUTE_PREFIX = "a_";

	/**
	 * Special property used to record actual Java types. Greycat V11 only stores
	 * int, long, double and String scalars and arrays. We have to keep the real
	 * type here and then convert back.
	 * 
	 * Only problem is that we can't really modify arrays in place - we have to
	 * replace them entirely with {@link #setProperty(String, Object)}.
	 */
	private static final String JAVATYPE_PROPERTY = "h_javatypes";
	private static final BiMap<String, Integer> javaTypes = HashBiMap.create();
	static {
		int counter = 0;
		for (Class<?> klass : Arrays.asList(Float.class,
			Double[].class, Float[].class, Long[].class, Integer[].class, Short[].class, Byte[].class,
			double[].class, float[].class, long[].class, int[].class, short[].class, byte[].class)) {
			javaTypes.put(klass.getSimpleName(), counter++);
		}
	}

	/** Greycat does not save empty strings into nodes, instead returning just null for them. We replace them with this placeholder value and map it back afterwards. */
	private static final String EMPTY_STRING_MARKER = "_@_h_empty_@_";

	private static final Logger LOGGER = LoggerFactory.getLogger(GreycatNode.class);

	private final AbstractGreycatDatabase db;
	private final long world, time, id;
	private final NodeProvider nodeProvider;

	/** lazily initialized node label */
	private String nodeLabel;

	protected static int getValueType(Object value) {
		if (value == null) {
			return Type.STRING;
		}

		switch (value.getClass().getSimpleName()) {
		case "boolean":
		case "Boolean":
			return Type.BOOL;
		case "Short":
		case "Byte":
		case "Integer":
			return Type.INT;
		case "Long":
			return Type.LONG;
		case "Float":
		case "Double":
			return Type.DOUBLE;
		case "String":
			return Type.STRING;
		}

		LOGGER.warn("Unknown type: {}, returning Type.STRING", value.getClass().getSimpleName());
		return Type.STRING;
	}

	/**
	 * For nodes that have been newly created and still need to be saved for the first time.
	 */
	public GreycatNode(AbstractGreycatDatabase db, long world, long time, long id, Node node) {
		this.db = db;
		this.world = world;
		this.time = time;
		this.id = id;

		this.nodeProvider = new NodeProvider(db.getGraph(), node);
		this.nodeProvider.markDirty();
	}

	@Override
	public Long getId() {
		return id;
	}

	public long getWorld() {
		return world;
	}

	@Override
	public long getTime() {
		return time;
	}

	@Override
	public void end() {
		try (NodeReader rn = getNodeReader()) {
			// 1. Unlink node from next endpoint
			// 2. Unindex node from next endpoint
			// 3. End node lifespan in Greycat

			/*
			 * end() means that the edges and node should still be available at *this*
			 * precise timepoint, but not from the next timepoint onwards.
			 */
			for (IGraphEdge out : travelInTime(time + 1).getOutgoing()) {
				out.delete();
			}
			for (IGraphEdge in : travelInTime(time + 1).getIncoming()) {
				in.delete();
			}

			db.luceneIndexer.remove(travelInTime(time + 1));
			rn.get().end();
		}
	}

	@Override
	public GreycatNode travelInTime(long time) {
		if (time == NO_SUCH_INSTANT) {
			return null;
		}
		return db.lookup(world, time, id);
	}

	public String getNodeLabel() {
		if (nodeLabel == null) {
			try (NodeReader rn = getNodeReader()) {
				nodeLabel = rn.get().get(AbstractGreycatDatabase.NODE_LABEL_IDX).toString();
			}
		}

		return nodeLabel;
	}

	@Override
	public Set<String> getPropertyKeys() {
		try (NodeReader rn = getNodeReader()) {
			final Node n = rn.get();
			final Resolver resolver = n.graph().resolver();
			NodeState state = resolver.resolveState(n);

			final Set<String> results = new HashSet<>();
			state.each((attributeKey, elemType, elem) -> {
				final String resolveName = resolver.hashToString(attributeKey);
				if (resolveName != null && resolveName.startsWith(ATTRIBUTE_PREFIX)) {
					results.add(resolveName.substring(ATTRIBUTE_PREFIX.length()));
				}
			});

			return results;
		}
	}

	protected NodeReader getNodeReader() {
		return new NodeReader();
	}

	@Override
	public boolean isAlive() {
		try (NodeReader rn = getNodeReader()) {
			return rn.get() != null;
		}
	}

	@Override
	public Object getProperty(String name) {
		Object rawValue;
		try (NodeReader rn = getNodeReader()) {
			rawValue = rn.get().get(ATTRIBUTE_PREFIX + name);

			if (rawValue instanceof StringArray) {
				return ((StringArray) rawValue).extract();
			} else if (rawValue instanceof LongArray) {
				final int javaTypeID = getJavaTypesMap(rn).getValue(name);
				final String javaType = javaTypes.inverse().get(javaTypeID);
				final LongArray lArray = (LongArray) rawValue;

				if ("Long[]".equals(javaType)) {
					Long[] ret = new Long[lArray.size()];
					for (int i = 0; i < lArray.size(); i++) {
						ret[i] = lArray.get(i);
					}
					return ret;
				}

				return lArray.extract();
			} else if (rawValue instanceof DoubleArray) {
				final int javaTypeID = getJavaTypesMap(rn).getValue(name);
				final String javaType = javaTypes.inverse().get(javaTypeID);
				final DoubleArray dArray = (DoubleArray) rawValue;

				switch (javaType) {
				case "Double[]": {
					Double[] ret = new Double[dArray.size()];
					for (int i = 0; i < dArray.size(); i++) {
						ret[i] = dArray.get(i);
					}
					return ret;
				}
				case "Float[]": {
					Float[] ret = new Float[dArray.size()];
					for (int i = 0; i < dArray.size(); i++) {
						ret[i] = (float) dArray.get(i);
					}
					return ret;
				}
				case "float[]": {
					float[] ret = new float[dArray.size()];
					for (int i = 0; i < dArray.size(); i++) {
						ret[i] = (float) dArray.get(i);
					}
					return ret;
				}
				}

				return dArray.extract();
			} else if (rawValue instanceof IntArray) {
				final int javaTypeID = getJavaTypesMap(rn).getValue(name);
				final String javaType = javaTypes.inverse().get(javaTypeID);
				final IntArray iArray = (IntArray) rawValue;

				switch (javaType) {
				case "Integer[]": {
					Integer[] ret = new Integer[iArray.size()];
					for (int i = 0; i < iArray.size(); i++) {
						ret[i] = iArray.get(i);
					}
					return ret;
				}
				case "Short[]": {
					Short[] ret = new Short[iArray.size()];
					for (int i = 0; i < iArray.size(); i++) {
						ret[i] = (short) iArray.get(i);
					}
					return ret;
				}
				case "short[]": {
					short[] ret = new short[iArray.size()];
					for (int i = 0; i < iArray.size(); i++) {
						ret[i] = (short) iArray.get(i);
					}
					return ret;
				}
				case "Byte[]": {
					Byte[] ret = new Byte[iArray.size()];
					for (int i = 0; i < iArray.size(); i++) {
						ret[i] = (byte) iArray.get(i);
					}
					return ret;
				}
				case "byte[]": {
					byte[] ret = new byte[iArray.size()];
					for (int i = 0; i < iArray.size(); i++) {
						ret[i] = (byte) iArray.get(i);
					}
					return ret;
				}
				}

				return iArray.extract();
			} else if (rawValue instanceof Double) {
				final int javaTypeID = getJavaTypesMap(rn).getValue(name);
				final String javaType = javaTypes.inverse().get(javaTypeID);

				if ("Float".equals(javaType)) {
					return ((Double) rawValue).floatValue();
				}
			} else if (EMPTY_STRING_MARKER.equals(rawValue)) {
				return "";
			}

			return rawValue;
		}
	}

	@Override
	public void setProperty(String name, Object value) {
		try (NodeReader rn = getNodeReader()) {
			setPropertyRaw(rn, name, value);
		}
	}

	/**
	 * Allows for setting multiple properties at once, in a slightly more efficient way.
	 */
	public void setProperties(Map<String, Object> props) {
		try (NodeReader rn = getNodeReader()) {
			setPropertiesRaw(rn, props);
		}
	}

	protected void setPropertiesRaw(NodeReader rn, Map<String, Object> props) {
		for (Entry<String, Object> entry : props.entrySet()) {
			setPropertyRaw(rn, entry.getKey(), entry.getValue());
		}
	}

	/**
	 * Saves the property, marking as dirty the node but without saving.
	 */
	protected void setPropertyRaw(NodeReader rn, String name, Object value) {
		if (value != null && value.getClass().isArray()) {
			setArrayPropertyRaw(rn, name, value);
		} else if (value instanceof Float) {
			getJavaTypesMap(rn).put(name, javaTypes.get(value.getClass().getSimpleName()));
			rn.get().set(ATTRIBUTE_PREFIX + name, Type.DOUBLE, value);
		} else {
			getJavaTypesMap(rn).remove(name);
			if ("".equals(value)) {
				value = EMPTY_STRING_MARKER;
			}
			rn.get().set(ATTRIBUTE_PREFIX + name, getValueType(value), value);
		}
		rn.markDirty();
	}

	protected void setArrayPropertyRaw(NodeReader rn, String name, Object value) {
		// Save real array type here, so we can convert back in getProperty()
		final String  javaType = value.getClass().getSimpleName();
		final Integer javaTypeID = javaTypes.get(javaType);
		if (javaTypeID != null) {
			final StringIntMap arrayTypes = getJavaTypesMap(rn);
			arrayTypes.put(name, javaTypeID);
		}
		final Node n = rn.get();

		switch (javaType) {
		case "Double[]":
		case "double[]":
		case "Float[]":
		case "float[]":
			DoubleArray dArray = (DoubleArray) n.getOrCreate(ATTRIBUTE_PREFIX + name, Type.DOUBLE_ARRAY);
			dArray.clear();

			switch (javaType) {
			case "Double[]":
				for (Double d : (Double[]) value) {
					if (d != null) {
						dArray.addElement(d);
					}
				}
				break;
			case "double[]":
				for (double d : (double[]) value) {
					dArray.addElement(d);
				}
				break;
			case "Float[]":
				for (Float f : (Float[]) value) {
					if (f != null) {
						dArray.addElement(f);
					}
				}
				break;
			case "float[]":
				for (float f : (float[]) value) {
					dArray.addElement(f);
				}
				break;
			}

			break;
		case "Long[]":
		case "long[]":
			LongArray lArray = (LongArray) n.getOrCreate(ATTRIBUTE_PREFIX + name, Type.LONG_ARRAY);
			lArray.clear();

			if ("Long".equals(javaType)) {
				for (long l : (Long[]) value) {
					lArray.addElement(l);
				}
			} else {
				for (long l : (long[]) value) {
					lArray.addElement(l);
				}
			}

			break;
		case "Integer[]":
		case "int[]":
		case "Short[]":
		case "short[]":
		case "Byte[]":
		case "byte[]":
			IntArray iArray = (IntArray) n.getOrCreate(ATTRIBUTE_PREFIX + name, Type.INT_ARRAY);
			iArray.clear();

			switch (javaType) {
			case "Integer[]":
				for (Integer i : (Integer[])value) {
					if (i != null) {
						iArray.addElement(i);
					}
				}
				break;
			case "int[]":
				for (int i : (int[])value) {
					iArray.addElement(i);
				}
				break;
			case "Short[]":
				for (Short i : (Short[])value) {
					if (i != null) {
						iArray.addElement(i);
					}
				}
				break;
			case "short[]":
				for (short i : (short[])value) {
					iArray.addElement(i);
				}
				break;
			case "Byte[]":
				for (Byte i : (Byte[])value) {
					if (i != null) {
						iArray.addElement(i);
					}
				}
				break;
			case "byte[]":
				for (byte i : (byte[])value) {
					iArray.addElement(i);
				}
				break;
			}

			break;
		case "String[]": {
			StringArray sArray = (StringArray) n.getOrCreate(ATTRIBUTE_PREFIX + name, Type.STRING_ARRAY);
			sArray.clear();
			sArray.addAll((String[]) value);
			break;
		}
		}
	}

	protected StringIntMap getJavaTypesMap(NodeReader rn) {
		StringIntMap value = (StringIntMap) rn.get().get(JAVATYPE_PROPERTY);
		if (value == null) {
			value = (StringIntMap) rn.get().getOrCreate(JAVATYPE_PROPERTY, Type.STRING_TO_INT_MAP);
			rn.markDirty();
		}
		return value;
	}

	@Override
	public Iterable<IGraphEdge> getEdges() {
		try (NodeReader rn = getNodeReader()) {
			return getAllEdges(rn, getAllEdges(rn, new ArrayList<>(), Direction.OUT), Direction.IN);
		}
	}

	@Override
	public IGraphIterable<IGraphEdge> getEdgesWithType(String type) {
		try (NodeReader rn = getNodeReader()) {
			final IGraphIterable<IGraphEdge> inEdges = getEdgesWithType(rn, Direction.IN, type);
			final IGraphIterable<IGraphEdge> outEdges = getEdgesWithType(rn, Direction.OUT, type);

			return new IGraphIterable<IGraphEdge>() {
				@Override
				public Iterator<IGraphEdge> iterator() {
					return Iterators.concat(inEdges.iterator(), outEdges.iterator());
				}

				@Override
				public int size() {
					return inEdges.size() + outEdges.size();
				}

				@Override
				public IGraphEdge getSingle() {
					if (inEdges.size() > 0) {
						return inEdges.getSingle();
					} else {
						return outEdges.getSingle();
					}
				}
			};
		}
	}

	@Override
	public IGraphIterable<IGraphEdge> getOutgoingWithType(String type) {
		try (NodeReader rn = getNodeReader()) {
			return getEdgesWithType(rn, Direction.OUT, type);
		}
	}

	@Override
	public IGraphIterable<IGraphEdge> getIncomingWithType(String type) {
		try (NodeReader rn = getNodeReader()) {
			return getEdgesWithType(rn, Direction.IN, type);
		}
	}

	protected IGraphIterable<IGraphEdge> getEdgesWithType(final NodeReader rn, final Direction dir, String type) {
		final int relationPosition = db.getGraph().resolver().stringToHash(dir.getPrefix() + type, false);
		final Relation relation = (Relation) rn.get().getAt(relationPosition);
		if (relation == null) {
			return new EmptyIGraphIterable<>();
		}

		/*
		 * Do NOT preload all target nodes, unlike traverse - doing so balloons memory
		 * usage in some cases (e.g. going from the file node to the instance nodes).
		 *
		 * Streaming the results should reduce the impact of this call - we may need only
		 * the first few elements anyway.
		 */
		final int nEdges = relation.size();

		return new IGraphIterable<IGraphEdge>() {
			@Override
			public Iterator<IGraphEdge> iterator() {
				return Iterators.transform(
					IntStream.range(0, nEdges).iterator(),
					i -> {
						final long nodeId = relation.get(i);
						final GreycatNode target = db.lookup(world, time, nodeId);
						return dir.convertToEdge(type, GreycatNode.this, target);
					}
				);
			}

			@Override
			public int size() {
				return relation.size();
			}

			@Override
			public IGraphEdge getSingle() {
				final long nodeId = relation.get(0);
				final GreycatNode target = db.lookup(world, time, nodeId);
				return dir.convertToEdge(type, GreycatNode.this, target);
			}
		};
	}

	@Override
	public Iterable<IGraphEdge> getIncoming() {
		try (NodeReader rn = getNodeReader()) {
			return getAllEdges(rn, new ArrayList<>(), Direction.IN);
		}
	}

	@Override
	public Iterable<IGraphEdge> getOutgoing() {
		try (NodeReader rn = getNodeReader()) {
			return getAllEdges(rn, new ArrayList<>(), Direction.OUT);
		}
	}

	protected List<IGraphEdge> getAllEdges(final NodeReader rn, final List<IGraphEdge> results, final Direction dir) {
		final Node n = rn.get();
		final Resolver resolver = n.graph().resolver();
		final NodeState state = resolver.resolveState(n);
		final String prefix = dir.getPrefix();

		state.each((attributeKey, elemType, elem) -> {
			if (elemType == Type.RELATION) {
				final String resolveName = resolver.hashToString(attributeKey);
				if (resolveName.startsWith(prefix)) {
					final String edgeType = resolveName.substring(prefix.length());
					Relation castedRelArr = (Relation) elem;
					for (int j = 0; j < castedRelArr.size(); j++) {
						final GreycatNode targetNode = db.lookup(world, time, castedRelArr.get(j));
						results.add(dir.convertToEdge(edgeType, this, targetNode));
					}
				}
			}
		});
		return results;
	}

	@Override
	public void delete() {
		if (db.currentMode() == Mode.NO_TX_MODE) {
			CompletableFuture<Boolean> cSaved = new CompletableFuture<>();
			db.hardDelete(this, dropped -> cSaved.complete(true));
			cSaved.join();
		} else {
			db.softDelete(this);
		}
	}

	@Override
	public AbstractGreycatDatabase getGraph() {
		return db;
	}

	@Override
	public void removeProperty(String name) {
		try (NodeReader rn = getNodeReader()) {
			rn.get().remove(ATTRIBUTE_PREFIX + name);
			rn.markDirty();
		}
	}

	@Override
	public void finalize() throws Throwable {
		super.finalize();
		nodeProvider.free();
	}

	/**
	 * Returns <code>true</code> if this element has been soft deleted.
	 * If so, it should be ignored by any queries and iterables.
	 */
	protected boolean isSoftDeleted() {
		try (NodeReader rn = getNodeReader()) {
			final Boolean softDeleted = (Boolean) rn.get().get(AbstractGreycatDatabase.SOFT_DELETED_KEY);
			return softDeleted == Boolean.TRUE;
		}
	}

	protected IGraphEdge addEdge(String type, GreycatNode end, Map<String, Object> props) {
		if (props == null || props.isEmpty()) {
			return GreycatLightEdge.create(type, this, end);
		} else {
			return GreycatHeavyEdge.create(type, this, end, props);
		}
	}

	protected static void addOutgoing(String type, final NodeReader rn, final NodeReader ro) {
		rn.get().addToRelation(Direction.OUT.getPrefix() + type, ro.get());
		rn.markDirty();
	}

	protected static void addIncoming(String type, final NodeReader rn, final NodeReader ro) {
		rn.get().addToRelation(Direction.IN.getPrefix() + type, ro.get());
		rn.markDirty();
	}

	protected static void removeOutgoing(String type, final NodeReader rn, final NodeReader ro) {
		rn.get().removeFromRelation(Direction.OUT.getPrefix() + type, ro.get());
		rn.markDirty();
	}

	protected static void removeIncoming(String type, final NodeReader rn, final NodeReader ro) {
		rn.get().removeFromRelation(Direction.IN.getPrefix() + type, ro.get());
		rn.markDirty();
	}

	@Override
	public String toString() {
		return "GreycatNode [world=" + world + ", time=" + time + ", id=" + id + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (id ^ (id >>> 32));
		result = prime * result + (int) (time ^ (time >>> 32));
		result = prime * result + (int) (world ^ (world >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		GreycatNode other = (GreycatNode) obj;
		if (id != other.id)
			return false;
		if (time != other.time)
			return false;
		if (world != other.world)
			return false;
		return true;
	}

	@Override
	public long getLatestInstant() throws Exception {
		try (NodeReader rn = getNodeReader()) {
			final Node n = rn.get();

			CompletableFuture<long[]> result = new CompletableFuture<>();
			n.timepoints(Constants.BEGINNING_OF_TIME, Constants.END_OF_TIME, (value) -> {
				result.complete(value);
			});

			long latest = Constants.BEGINNING_OF_TIME;
			for (long timepoint : result.get()) {
				latest = Math.max(latest, timepoint);
			}
			return latest;
		}
	}

	@Override
	public List<Long> getInstantsBetween(long fromInclusive, long toInclusive) {
		try (NodeReader rn = getNodeReader()) {
			final Node n = rn.get();

			CompletableFuture<long[]> result = new CompletableFuture<>();

			/*
			 * FIXME Greycat says that in timepoints(...), both ends are inclusive, but our
			 * unit tests say otherwise. This is a temporal fix, with some caution around
			 * overflow.
			 */
			n.timepoints(fromInclusive, toInclusive < Constants.END_OF_TIME ? toInclusive + 1 : toInclusive, (value) -> {
				result.complete(value);
			});

			List<Long> instants = new ArrayList<>();
			for (long instant : result.get()) {
				instants.add(instant);
			}
			return instants;
		} catch (InterruptedException e) {
			LOGGER.error(e.getMessage(), e);
			Thread.currentThread().interrupt();
			return Collections.emptyList();
		} catch (ExecutionException e) {
			LOGGER.error(e.getMessage(), e);
			return Collections.emptyList();
		}
	}

	@Override
	public long getEarliestInstant() throws Exception {
		try (NodeReader rn = getNodeReader()) {
			final Node n = rn.get();

			CompletableFuture<long[]> result = new CompletableFuture<>();
			n.timepoints(Constants.BEGINNING_OF_TIME, Constants.END_OF_TIME, (value) -> {
				result.complete(value);
			});

			long earliest = Constants.END_OF_TIME;
			for (long timepoint : result.get()) {
				earliest = Math.min(earliest, timepoint);
			}
			return earliest;
		}
	}

	@Override
	public long getPreviousInstant() throws Exception {
		try (NodeReader rn = getNodeReader()) {
			final Node n = rn.get();

			CompletableFuture<long[]> result = new CompletableFuture<>();

			/*
			 * While the GreyCat javadocs say that both ends of the timepoints range are
			 * inclusive, the TimeAwareBackendTest#nextPrev method showed that the end of
			 * the range is exclusive.
			 */
			n.timepoints(Constants.BEGINNING_OF_TIME, getTime(),
				(value) -> result.complete(value));

			/*
			 * We assume timepoints(...) produces elements from newest to oldest. The
			 * previous instant is the most recent moment before the current one.
			 */
			final long[] instants = result.get();
			if (instants.length == 0) {
				return NO_SUCH_INSTANT;
			}
			return instants[0];
		}
	}

	@Override
	public long getNextInstant() throws Exception {
		try (NodeReader rn = getNodeReader()) {
			final Node n = rn.get();

			CompletableFuture<long[]> result = new CompletableFuture<>();
			n.timepoints(getTime() + 1, Constants.END_OF_TIME, (value) -> {
				result.complete(value);
			});

			// See getPreviousInstant() for our assumptions
			final long[] instants = result.get();
			if (instants.length == 0) {
				return NO_SUCH_INSTANT;
			}
			return instants[instants.length - 1];
		}
	}

	@Override
	public List<Long> getInstantsFrom(long fromInclusive) {
		return getInstantsBetween(fromInclusive, Constants.END_OF_TIME);
	}

	@Override
	public List<Long> getInstantsUpTo(long toInclusive) {
		return getInstantsBetween(Constants.BEGINNING_OF_TIME, toInclusive);
	}

	@Override
	public List<Long> getAllInstants() throws Exception {
		return getInstantsBetween(Constants.BEGINNING_OF_TIME, Constants.END_OF_TIME);
	}

}
