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

import static org.eclipse.statet.rj.server.util.ServerUtils.MISSING_ANSWER_STATUS;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.OutputStream;
import java.rmi.ConnectException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.eclipse.statet.jcommons.lang.NonNull;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.status.ErrorStatus;
import org.eclipse.statet.jcommons.status.InfoStatus;
import org.eclipse.statet.jcommons.status.NullProgressMonitor;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.Status;
import org.eclipse.statet.jcommons.status.StatusException;
import org.eclipse.statet.jcommons.status.WarningStatus;

import org.eclipse.statet.rj.RjException;
import org.eclipse.statet.rj.data.REnvironment;
import org.eclipse.statet.rj.data.RJIO;
import org.eclipse.statet.rj.data.RJIOExternalizable;
import org.eclipse.statet.rj.data.RList;
import org.eclipse.statet.rj.data.RObject;
import org.eclipse.statet.rj.data.RReference;
import org.eclipse.statet.rj.server.BinExchange;
import org.eclipse.statet.rj.server.ComHandler;
import org.eclipse.statet.rj.server.ConsoleReadCmdItem;
import org.eclipse.statet.rj.server.CtrlCmdItem;
import org.eclipse.statet.rj.server.DataCmdItem;
import org.eclipse.statet.rj.server.DataCmdItem.Operation;
import org.eclipse.statet.rj.server.DbgCmdItem;
import org.eclipse.statet.rj.server.ExtClientCmdItem;
import org.eclipse.statet.rj.server.GDCmdItem;
import org.eclipse.statet.rj.server.GraOpCmdItem;
import org.eclipse.statet.rj.server.MainCmdC2SList;
import org.eclipse.statet.rj.server.MainCmdItem;
import org.eclipse.statet.rj.server.MainCtrlCmdItem;
import org.eclipse.statet.rj.server.REngine;
import org.eclipse.statet.rj.server.RjsComConfig;
import org.eclipse.statet.rj.server.RjsComObject;
import org.eclipse.statet.rj.server.RjsPing;
import org.eclipse.statet.rj.server.RjsStatus;
import org.eclipse.statet.rj.server.Server;
import org.eclipse.statet.rj.server.client.RClientGraphic.InitConfig;
import org.eclipse.statet.rj.server.dbg.CtrlReport;
import org.eclipse.statet.rj.services.RPlatform;
import org.eclipse.statet.rj.services.RService;


/**
 * Generic RJ Com protocol client for servers offering a {@link REngine}.
 * <p>
 * It offers basic implementation for most methods of the {@link RService} API,
 * including:</p>
 * <ul>
 *   <li>Expression evaluation</li>
 *   <li>Data exchange to assign or eval/read {@link RObject}</li>
 *   <li>File exchange to write/read file on the server (must be enabled at server side)</li>
 *   <li>R graphics (requires an {@link RClientGraphicFactory}, set in {@link #initGraphicFactory()},
 *       or via {@link #setGraphicFactory(RClientGraphicFactory, RClientGraphicActions)})</li>
 *   <li>Console (REPL), if connected to server slot 0</li>
 * </ul>
 * <p>
 * If offers two mechanisms allowing the usage of RService API and R thread when they are already
 * used by a regular call. So the two modes allows to "hijack" the R thread to "inject" additional
 * calls to the RService API:</p>
 * <ul>
 *   <li>Hot Mode: Enables to run code in any situation, also if R is busy. Nesting of hot modes is
 *       not possible. It can be requested asynchronous from any thread. The hot mode is appropriate
 *       for e.g. short task for the GUI.</li>
 *   <li>Extra Mode: Enables to run code at the before or after of a client-server communication.
 *       Must be requested synchronous from the R thread.</li>
 * </ul>
 */
public abstract class AbstractRJComClient implements ComHandler {
	
	
	public static final @NonNull String RJ_CLIENT_ID= "org.eclipse.statet.rj.client"; //$NON-NLS-1$
	
	public static int[] version() {
		return new int[] { 4, 0, 0 };
	}
	
	public static final int EXTRA_BEFORE= 1;
	public static final int EXTRA_NESTED= 2;
	
	private static final ScheduledExecutorService RJHelper_EXECUTOR =
			Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory("RJHelper"));
	
	private static final Random RAND= new Random();
	
	
	private final static class RunnableList {
		
		private Runnable[] array;
		private int size;
		
		public RunnableList() {
			this.array= new Runnable[4];
			this.size= 0;
		}
		
		
		public void add(final Runnable value) {
			if (value == null) {
				throw new IllegalArgumentException();
			}
			final int oldCapacity= this.array.length;
			if (this.size < oldCapacity) {
				this.array[this.size++]= value;
				return;
			}
			final Runnable[] newArray= new Runnable[oldCapacity + 4];
			System.arraycopy(this.array, 0, newArray, 0, oldCapacity);
			newArray[this.size++]= value;
			this.array= newArray;
		}
		
		public boolean isNotEmpty() {
			return (this.size != 0);
		}
		
		public Runnable[] consume() {
			final Runnable[] oldListeners= this.array;
			this.size= 0;
			this.array= new Runnable[4];
			return oldListeners;
		}
		
	}
	
	
	private class KeepAliveRunnable implements Runnable {
		
		@Override
		public void run() {
			runAsyncPing();
		}
		
	}
	
	private class HotModeRequestRunnable implements Runnable {
		
		@Override
		public void run() {
			if (AbstractRJComClient.this.hotModeRequested.get()) {
				try {
					runAsyncCtrl(CtrlCmdItem.REQUEST_HOT_MODE);
				}
				catch (final StatusException e) {
					if (e.getStatus().getSeverity() != Status.CANCEL) {
						log(new ErrorStatus(RJ_CLIENT_ID,
								"An error occurred when requesting hot mode.",
								e ));
					}
				}
			}
		}
	}
	
	
	private RService rService;
	private Object rHandle;
	
	private ProgressMonitor progressMonitor;
	
	private final RJIO mainIO= new RJIO();
	private MainCmdItem mainC2SFirst;
	private final MainCmdC2SList mainC2SList= new MainCmdC2SList(this.mainIO);
	private final RunnableList mainDeferredCmds= new RunnableList();
	private boolean mainRunGC;
	
	private boolean consoleReadCallbackRequired;
	private ConsoleReadCmdItem consoleReadCallback;
	
	private final Object platformLock= new Object();
	private Map<String, Object> platformData;
	private RPlatform platformObj;
	
	private final byte randomId= (byte) (0xff & RAND.nextInt(255));
	
	private int dataLevelRequest= 0;
	private int dataLevelAnswer= 0;
	private int dataLevelIgnore= 0;
	private byte dataRequestCounter= (byte) (0xff & RAND.nextInt(255));
	private final int[] dataRequestId= new int[32];
	private final MainCmdItem[] dataAnswer= new MainCmdItem[32];
	
	private boolean runFinishTask;
	
	private boolean dbgOpRequest;
	private DbgCmdItem dbgOpAnswer;
	
	private int hotModeState;
	private ConsoleReadCmdItem hotModeReadCallbackBackup;
	private MainCmdItem hotModeC2SFirstBackup;
	private final AtomicBoolean hotModeRequested= new AtomicBoolean();
	private final Runnable hotModeRunnable= new HotModeRequestRunnable();
	
	private int extraModeRequested;
	
	private RClientGraphicFactory graphicFactory;
	private @Nullable RClientGraphicActions graphicActions;
	private final RClientGraphic graphicDummy= new RClientGraphicDummy(1, 0, 0);
	private RClientGraphic[] graphics= new RClientGraphic[16];
	private int currentGraphicOptions;
	private RClientGraphic lastGraphic;
	
	private REngine rjConsoleEngine;
	
	private List<Runnable> defferedRunnables;
	
	private boolean closed;
	private ScheduledFuture<?> periodicCheckJob;
	private String closedMessage= "Connection to R engine is closed.";
	
	private final Lock clientWaitLock= new ReentrantLock();
	private final Condition clientWaitCondition= this.clientWaitLock.newCondition();
	private final List<Callable<Boolean>> cancelHandler= new ArrayList<>();
	
	
	protected AbstractRJComClient() {
	}
	
	
	public void initClient(final Object rHandle, final RService r,
			final Map<String, Object> properties, final int id) {
		this.rHandle= rHandle;
		this.rService= r;
		properties.put("rj.com.init", Boolean.TRUE); //$NON-NLS-1$
		properties.put(RjsComConfig.RJ_COM_S2C_ID_PROPERTY_ID, id);
		
		try {
			initGraphicFactory();
		}
		catch (final Exception e) {
			log(new ErrorStatus(RJ_CLIENT_ID,
					"An error occurred when initializing R client graphic factory.",
					e ));
		}
		if (this.graphicFactory != null) {
			final Map<String, ? extends Object> additional= this.graphicFactory.getInitServerProperties();
			if (additional != null) {
				properties.putAll(additional);
			}
		}
		else {
			this.graphicFactory= new RClientGraphicDummyFactory();
			log(new WarningStatus(RJ_CLIENT_ID,
					"No R client graphic factory configured." ));
		}
	}
	
	public final void setServer(final REngine rjServer, final int client) {
		final List<Runnable> runnables;
		synchronized (this) {
			this.rjConsoleEngine= rjServer;
			if (client == 0) {
				int t= 45 * 1000;
				try {
					final String p= System.getProperty("org.eclipse.statet.rj.client.keepaliveInterval"); //$NON-NLS-1$
					if (p != null && p.length() > 0) {
						t= Integer.parseInt(p);
					}
				}
				catch (final Exception e) {}
				initPeriodicCheck(new KeepAliveRunnable(), t);
			}
			runnables= this.defferedRunnables;
			this.defferedRunnables= null;
		}
		if (runnables != null) {
			for (int i= 0; i < runnables.size(); i++) {
				RJHelper_EXECUTOR.execute(runnables.get(i));
			}
		}
	}
	
	public void initPeriodicCheck(final Runnable runnable, final int intervalMillis) {
		this.periodicCheckJob= RJHelper_EXECUTOR.scheduleWithFixedDelay(
				runnable, 1000, intervalMillis, TimeUnit.MILLISECONDS );
	}
	
	public Object getRHandle() {
		return this.rHandle;
	}
	
	public RService getRService() {
		return this.rService;
	}
	
	public final REngine getConsoleEngine() {
		return this.rjConsoleEngine;
	}
	
	protected void execAsync(final Runnable runnable) {
		synchronized (this) {
			if (this.rjConsoleEngine == null) {
				if (this.defferedRunnables == null) {
					this.defferedRunnables= new ArrayList<>(8);
				}
				this.defferedRunnables.add(runnable);
				return;
			}
		}
		RJHelper_EXECUTOR.execute(runnable);
	}
	
	protected void initGraphicFactory() {
	}
	
	
	public final void setGraphicFactory(final RClientGraphicFactory factory,
			final @Nullable RClientGraphicActions actions) {
		if (factory == null) {
			throw new NullPointerException();
		}
		this.graphicFactory= factory;
		this.graphicActions= actions;
	}
	
	public boolean isClosed() {
		return this.closed;
	}
	
	public void setClosed(final boolean closed) {
		if (this.closed != closed) {
			this.closed= closed;
			if (closed) {
				final ScheduledFuture<?> job= this.periodicCheckJob;
				if (job != null) {
					this.periodicCheckJob= null;
					job.cancel(true);
				}
			}
		}
	}
	
	public void setRjsProperties(final Map<String, ? extends Object> properties) throws StatusException {
		try {
			this.rjConsoleEngine.setProperties(properties);
		}
		catch (final RemoteException e) {
			throw new StatusException(new ErrorStatus(RJ_CLIENT_ID,
					"An error occurred when setting server properties.",
					e ));
		}
	}
	
	
	@Override
	public final void processMainCmd(final ObjectInput in) throws IOException {
		boolean runGC= false;
		updateBusy(in.readBoolean());
		if (this.hotModeState == 4) {
			this.hotModeState= 0;
			this.consoleReadCallback= this.hotModeReadCallbackBackup;
			this.hotModeReadCallbackBackup= null;
			if (this.hotModeC2SFirstBackup != null) {
				addC2SCmd(this.hotModeC2SFirstBackup);
				this.hotModeC2SFirstBackup= null;
			}
		}
		
		this.mainIO.connect(in);
		final int check= this.mainIO.readCheck1();
		
		while (true) {
			final byte type= in.readByte();
			switch (type) {
			case MainCmdItem.T_NONE:
				this.mainIO.readCheck2(check);
				this.mainIO.disconnect(in);
				this.mainRunGC= runGC;
				return;
			case MainCmdItem.T_CONSOLE_READ_ITEM:
				processPrompt(new ConsoleReadCmdItem(this.mainIO));
				continue;
			case MainCmdItem.T_CONSOLE_WRITE_ITEM:
				runGC= true;
				writeConsoleOutput(this.mainIO.readByte(), this.mainIO.readString());
				continue;
			case MainCmdItem.T_MESSAGE_ITEM:
				runGC= true;
				showMessage(this.mainIO.readString());
				continue;
			case MainCmdItem.T_EXT_CLIENT_ITEM:
				runGC= true;
				processUICallback(this.mainIO);
				continue;
			case MainCmdItem.T_GRAPH_ITEM:
				runGC= true;
				processGDCmd(this.mainIO);
				continue;
			case MainCmdItem.T_MAIN_CTRL_ITEM:
				runGC= true;
				processMainCtrlCmd(this.mainIO);
				continue;
			case MainCmdItem.T_DATA_ITEM:
				runGC= true;
				processDataCmd(this.mainIO);
				continue;
			case MainCmdItem.T_GRAPHICS_OP_ITEM:
				runGC= true;
				processGraphicsOpCmd(this.mainIO);
				continue;
			case MainCmdItem.T_DBG_ITEM:
				runGC= true;
				processDbgCmd(this.mainIO);
				continue;
			default:
				this.mainIO.disconnect(in);
				throw new IOException("Unknown cmdtype id: " + type);
			}
		}
	}
	
	private final void processCmdDeferred(final Runnable runnable) {
		this.mainDeferredCmds.add(runnable);
	}
	
	
	public final boolean processUICallback(final RJIO io) throws IOException {
		final ExtClientCmdItem item= new ExtClientCmdItem(io);
		try {
			final RList answer= handleUICallback(item.getDataText(), item.getDataArgs(),
					this.progressMonitor);
			item.setAnswer(answer);
		}
		catch (final IOException e) {
			throw e;
		}
		catch (final Exception e) {
			log(new ErrorStatus(RJ_CLIENT_ID,
					"An error occurred when exec RJ UI command '" + item.getDataText() + "'.",
					e ));
			if (item.waitForClient()) {
				item.setAnswer(new RjsStatus(RjsStatus.ERROR, 0, "Client error processing current command."));
			}
		}
		if (item.waitForClient()) {
			addC2SCmd(item);
			return true;
		}
		return false;
	}
	
	protected RList handleUICallback(final String commandId, final RList args,
			final ProgressMonitor m) throws Exception {
		throw new StatusException(new WarningStatus(RJ_CLIENT_ID,
				String.format("Unhandled RJ UI command '%1$s'.", commandId) ));
	}
	
	
	public final void processGDCmd(final RJIO io) throws IOException {
		final int devId;
		final int options;
		{	final int i= io.readInt();
			options= (i & MainCmdItem.OV_WAITFORCLIENT);
			devId= (i & ~MainCmdItem.OV_WAITFORCLIENT);
		}
		byte requestId= -1;
		try {
			switch (io.readByte()) {
			case GDCmdItem.C_NEW_PAGE:
				addGraphic(devId,
						io.readDouble(),
						io.readDouble(),
						io.readInt(),
						io.readBoolean() );
				return;
			case GDCmdItem.C_CLOSE_DEVICE:
				removeGraphic(devId);
				return;
			case GDCmdItem.C_GET_SIZE:
				addC2SCmd(new GDCmdItem.DoubleAnswer(requestId= io.readByte(),
						devId, getGraphic(devId).computeSize() ));
				return;
			case GDCmdItem.C_SET_ACTIVE_OFF:
				getGraphic(devId).setActive(false);
				return;
			case GDCmdItem.C_SET_ACTIVE_ON:
				getGraphic(devId).setActive(true);
				return;
			case GDCmdItem.C_SET_MODE:
				getGraphic(devId).setMode(io.readByte());
				return;
			case GDCmdItem.C_GET_FONTMETRIC:
				addC2SCmd(new GDCmdItem.DoubleAnswer(requestId= io.readByte(),
						devId, getGraphic(devId).computeFontMetric(
								io.readInt() )));
				return;
			case GDCmdItem.C_GET_STRINGWIDTH:
				addC2SCmd(new GDCmdItem.DoubleAnswer(requestId= io.readByte(),
						devId, getGraphic(devId).computeStringWidth(
								io.readString() )));
				return;
				
			case GDCmdItem.SET_CLIP:
				getGraphic(devId).addSetClip(
						io.readDouble(),
						io.readDouble(),
						io.readDouble(),
						io.readDouble() );
				return;
			case GDCmdItem.SET_COLOR:
				getGraphic(devId).addSetColor(
						io.readInt() );
				return;
			case GDCmdItem.SET_FILL:
				getGraphic(devId).addSetFill(
						io.readInt() );
				return;
			case GDCmdItem.SET_LINE:
				getGraphic(devId).addSetLine(
						io.readInt(),
						io.readFloat(),
						io.readByte(),
						io.readByte(),
						io.readFloat() );
				return;
			case GDCmdItem.SET_FONT:
				getGraphic(devId).addSetFont(
						io.readString(),
						io.readInt(),
						io.readFloat(),
						io.readFloat() );
				return;
				
			case GDCmdItem.DRAW_LINE:
				getGraphic(devId).addDrawLine(
						io.readDouble(),
						io.readDouble(),
						io.readDouble(),
						io.readDouble() );
				return;
			case GDCmdItem.DRAW_RECTANGLE:
				getGraphic(devId).addDrawRect(
						io.readDouble(),
						io.readDouble(),
						io.readDouble(),
						io.readDouble() );
				return;
			case GDCmdItem.DRAW_POLYLINE:
				getGraphic(devId).addDrawPolyline(
						io.readDoubleArray(),
						io.readDoubleArray2() );
				return;
			case GDCmdItem.DRAW_POLYGON:
				getGraphic(devId).addDrawPolygon(
						io.readDoubleArray(),
						io.readDoubleArray2() );
				return;
			case GDCmdItem.DRAW_PATH:
				getGraphic(devId).addDrawPath(
						io.readIntArray(),
						io.readDoubleArray(),
						io.readDoubleArray2(),
						io.readInt() );
				return;
			case GDCmdItem.DRAW_CIRCLE:
				getGraphic(devId).addDrawCircle(
						io.readDouble(),
						io.readDouble(),
						io.readDouble() );
				return;
			case GDCmdItem.DRAW_TEXT:
				getGraphic(devId).addDrawText(
						io.readString(),
						io.readDouble(),
						io.readDouble(),
						io.readDouble(),
						io.readDouble() );
				return;
			case GDCmdItem.DRAW_RASTER:
				getGraphic(devId).addDrawRaster(
						io.readByteArray(),
						io.readBoolean(),
						io.readInt(),
						io.readInt(),
						io.readDouble(),
						io.readDouble(),
						io.readDouble(),
						io.readDouble(),
						io.readDouble(),
						io.readBoolean() );
				return;
				
			case GDCmdItem.CAPTURE:
				addC2SCmd(new GDCmdItem.Answer(requestId= io.readByte(),
						devId, getGraphic(devId).capture(
								io.readInt(),
								io.readInt() )));
				return;
				
			case GDCmdItem.U_LOCATOR: {
				final byte fid= requestId= io.readByte();
				processCmdDeferred(new Runnable() {
					@Override
					public void run() {
						addC2SCmd(new GDCmdItem.DoubleAnswer(fid,
								devId, getGraphic(devId).runRLocator(
										AbstractRJComClient.this.rService,
										AbstractRJComClient.this.progressMonitor )));
					}
				});
				return; }
				
			default:
				if ((options & MainCmdItem.OV_WAITFORCLIENT) != 0) {
					requestId= io.readByte();
				}
				throw new UnsupportedOperationException("Unknown GD command.");
			}
		}
		catch (final IOException e) {
			throw e;
		}
		catch (final Throwable e) {
			log(new ErrorStatus(RJ_CLIENT_ID,
					"An error occurred when processing graphic command.",
					e ));
			if (requestId >= 0) {
				addC2SCmd(new GDCmdItem.Answer(requestId, devId, new RjsStatus(RjsStatus.ERROR, 0)));
			}
//			throw new RuntimeException(e);
		}
	}
	
	
	private final void processMainCtrlCmd(final RJIO io) throws IOException {
		try {
			final MainCtrlCmdItem item= new MainCtrlCmdItem(io);
			addDataAnswer(item);
		}
		catch (final IOException e) {
			throw e;
		}
		catch (final Exception e) {
			log(new ErrorStatus(RJ_CLIENT_ID,
					"An error occurred when processing control command answer.",
					e ));
		}
	}
	
	private final void processDataCmd(final RJIO io) throws IOException {
		try {
			final DataCmdItem item= new DataCmdItem(io);
			addDataAnswer(item);
		}
		catch (final IOException e) {
			throw e;
		}
		catch (final Exception e) {
			log(new ErrorStatus(RJ_CLIENT_ID,
					"An error occurred when processing data command answer.",
					e ));
		}
	}
	
	private final void processGraphicsOpCmd(final RJIO io) throws IOException {
		try {
			final GraOpCmdItem item= new GraOpCmdItem(io);
			addDataAnswer(item);
		}
		catch (final IOException e) {
			throw e;
		}
		catch (final Exception e) {
			log(new ErrorStatus(RJ_CLIENT_ID,
					"An error occurred when processing graphic operation answer.",
					e ));
		}
	}
	
	private final int newDataLevel() {
		final int level= ++this.dataLevelRequest;
		if (level >= this.dataAnswer.length) {
			this.dataLevelRequest--;
			throw new UnsupportedOperationException("too much nested operations");
		}
		this.dataLevelAnswer= 0;
		
		return level;
	}
	
	private final MainCmdItem createDataRequestId(final int level, final MainCmdItem item) {
		this.dataRequestId[level]= ((((0xff) & item.getCmdType()) << 24)
				| ((0xff & item.getOp()) << 16)
				| ((0xff & this.randomId << 8))
				| ((0xff & ++this.dataRequestCounter)) );
		item.requestId= (((0xff & level) << 24) | (0xffffff & this.dataRequestId[level]));
		return item;
	}
	
	private final void addDataAnswer(final MainCmdItem item) throws RjException {
		final int level= (((0xff000000) & item.requestId) >>> 24);
		if (level > 0 && level <= this.dataLevelRequest
				&& this.dataRequestId[level] == (((0xff & item.getCmdType()) << 24)
						| (0xffffff & item.requestId)) ) {
			this.dataAnswer[level]= item;
			this.dataLevelAnswer= level;
			return;
		}
		if ((item.requestId & 0xff00 >>> 8) != (this.randomId & 0xff)) {
			// other client
//			System.out.println("Other client: " + item);
			return;
		}
		throw new RjException("Unexpected server answer: " + item);
	}
	
	private final void finalizeDataLevel() {
		final int level= this.dataLevelRequest--;
		this.dataAnswer[level]= null;
		this.dataLevelAnswer= (this.dataAnswer[this.dataLevelRequest] != null) ? this.dataLevelRequest : 0;
		
		this.runFinishTask= true;
	}
	
	public final int getDataLevel() {
		return this.dataLevelRequest;
	}
	
	
	protected final void processDbgCmd(final RJIO io) throws IOException {
		final DbgCmdItem item= new DbgCmdItem(io);
		if (item.getOp() > DbgCmdItem.OP_C2S_S2C) {
			handleDbgEvents(item.getOp(), item.getData());
		}
		else if (this.dbgOpRequest) {
			this.dbgOpAnswer= item;
		}
	}
	
	protected void handleDbgEvents(final byte dbgOp, final Object events) {
	}
	
	
	protected abstract void log(final Status status);
	
	protected abstract void handleServerStatus(final RjsStatus serverStatus,
			final ProgressMonitor m) throws StatusException;
	
	protected abstract void handleStatus(final Status status, final ProgressMonitor m);
	
	protected void scheduleConnectionCheck() {
	}
	
	
	public final boolean runAsyncPing() {
		try {
			final RjsComObject answer= this.rjConsoleEngine.runAsync(RjsPing.INSTANCE);
			if (answer instanceof RjsStatus) {
				final RjsStatus status= (RjsStatus) answer;
				if (status.getSeverity() == RjsStatus.OK) {
					return true;
				}
				scheduleConnectionCheck();
			}
		}
		catch (final ConnectException e) {
			scheduleConnectionCheck();
		}
		catch (final RemoteException e) {
			// TODO if (rmiregistry is available) scheduleCheck();
			// no need to log here
		}
		catch (final Exception e) {
		}
		return false;
	}
	
	public final boolean runAsyncInterrupt() {
		final Callable<Boolean>[] handlers= getCancelHandlers();
		for (int i= handlers.length - 1; i >= 0; i--) {
			try {
				final Boolean done= handlers[i].call();
				if (done != null && done.booleanValue()) {
					return false;
				}
			}
			catch (final Exception e) {
				// handler failed
			}
		}
		final ProgressMonitor monitor= this.progressMonitor;
		if (monitor != null) {
			monitor.setCanceled(true);
		}
		try {
			runAsyncCtrl(CtrlCmdItem.REQUEST_CANCEL);
			return true;
		}
		catch (final StatusException e) {
			if (e.getStatus().getSeverity() != Status.CANCEL) {
				log(new ErrorStatus(RJ_CLIENT_ID,
						"An error occurred when trying to interrupt R.",
						e ));
			}
			return false;
		}
	}
	
	public final void runAsyncCtrl(final int id) throws StatusException {
		final RjsStatus status= (RjsStatus) runAsync(new CtrlCmdItem(id));
		if (status.getSeverity() != RjsStatus.OK) {
			throw new StatusException(Status.newStatus(status.getSeverity(), RJ_CLIENT_ID,
					String.format("Executing CTRL command failed with code= 0x%1$08X.",
							status.getCode() )));
		}
	}
	
	public final RjsComObject runAsync(final RjsComObject com) throws StatusException {
		if (this.closed) {
			throw new StatusException(new ErrorStatus(RJ_CLIENT_ID, this.closedMessage));
		}
		try {
			return this.rjConsoleEngine.runAsync(com);
		}
		catch (final Exception e) {
			throw new StatusException(new ErrorStatus(RJ_CLIENT_ID, "Communication error.", e));
		}
	}
	
	public final void runMainLoopPing(final ProgressMonitor m) throws StatusException {
		try {
			this.mainRunGC= false;
			final RjsStatus status= (RjsStatus) this.rjConsoleEngine.runMainLoop(RjsPing.INSTANCE);
			if (status.getSeverity() == RjsStatus.OK) {
				return;
			}
			handleServerStatus(status, m);
		}
		catch (final ConnectException e) {
			handleServerStatus(new RjsStatus(RjsStatus.INFO, Server.S_DISCONNECTED), m);
		}
		catch (final Exception e) {
			// no need to log here
			handleServerStatus(new RjsStatus(RjsStatus.INFO, Server.S_LOST), m);
		}
	}
	
	public final void runMainLoop(RjsComObject sendCom, MainCmdItem sendItem,
			final ProgressMonitor m) throws StatusException {
		if (this.closed) {
			throw new StatusException(new ErrorStatus(RJ_CLIENT_ID, this.closedMessage));
		}
		final boolean loopReadCallbackIgnore= !this.consoleReadCallbackRequired;
		final int loopDataLevelIgnore= this.dataLevelIgnore;
		try {
			if ((this.extraModeRequested & EXTRA_BEFORE) != 0 && this.hotModeState < 1) {
				this.extraModeRequested= 0;
				this.dataLevelIgnore= this.dataLevelRequest;
				processExtraMode(EXTRA_BEFORE);
			}
			while (this.hotModeRequested.get()
					&& this.hotModeState < 1 && !this.dbgOpRequest) {
				this.dataLevelIgnore= this.dataLevelRequest;
				startHotMode();
			}
			this.progressMonitor= m;
			int ok= 0;
			while (!this.closed) {
				try {
					RjsComObject receivedCom= null;
					if (sendItem != null) {
						if (sendItem.getCmdType() == MainCmdItem.T_CONSOLE_READ_ITEM) {
							this.consoleReadCallback= null;
						}
						this.mainC2SList.setObjects(sendItem);
						sendCom= this.mainC2SList;
						sendItem= null;
					}
	//				System.out.println("client *-> server: " + sendCom);
					this.mainRunGC= false;
					receivedCom= this.rjConsoleEngine.runMainLoop(sendCom);
					this.mainC2SList.clear();
					sendCom= null;
	//				System.out.println("client *<- server: " + receivedCom);
					switch (receivedCom.getComType()) {
					case RjsComObject.T_PING:
						ok= 0;
						sendCom= RjsStatus.OK_STATUS;
						continue;
					case RjsComObject.T_MAIN_LIST:
						if (this.mainDeferredCmds.isNotEmpty()) {
							final Runnable[] runnables= this.mainDeferredCmds.consume();
							for (int i= 0; i < runnables.length; i++) {
								if (runnables[i] != null) {
									try {
										runnables[i].run();
									}
									catch (final Exception e) {
										log(new ErrorStatus(RJ_CLIENT_ID,
												"An error occurred when running a deferred command.",
												e ));
									}
								}
							}
						}
						ok= 0;
						switch (this.hotModeState) {
						case 1:
							sendCom= this.mainC2SList; // repeat
							continue;
						case 2:
							this.hotModeState= 3;
							this.hotModeRequested.set(false);
							this.dataLevelIgnore= this.dataLevelRequest;
							try {
								processHotMode();
								continue;
							}
							finally {
								this.progressMonitor= m;
								this.hotModeState= 4;
								this.consoleReadCallback.setAnswer(RjsStatus.OK_STATUS);
								sendItem= this.consoleReadCallback;
							}
						default:
							while (!this.closed
									&& (sendItem= getC2SCmds()) == null
									&& (loopReadCallbackIgnore || this.consoleReadCallback != null)
									&& (this.dataLevelRequest <= loopDataLevelIgnore
											|| this.dataLevelRequest == this.dataLevelAnswer
											|| (this.extraModeRequested & EXTRA_NESTED) != 0 )
									&& (this.dbgOpRequest == (this.dbgOpAnswer != null))) {
								if (this.mainRunGC) {
									this.mainRunGC= false;
									this.rjConsoleEngine.runMainLoop(RjsPing.INSTANCE);
								}
								if ((this.extraModeRequested & EXTRA_NESTED) != 0 && this.hotModeState < 1) {
									this.extraModeRequested= 0;
									this.dataLevelIgnore= this.dataLevelRequest;
									try {
										processExtraMode(EXTRA_NESTED);
										continue; // validate again
									}
									finally {
										this.progressMonitor= m;
									}
								}
								else {
									return; // finished
								}
							}
							continue;
						}
					case RjsComObject.T_STATUS:
						ok= 0;
						processStatus((RjsStatus) receivedCom, m);
						sendCom= this.mainC2SList;
						continue;
					}
				}
				catch (final ConnectException e) {
					handleServerStatus(new RjsStatus(RjsStatus.INFO, Server.S_DISCONNECTED), m);
					return;
				}
				catch (final RemoteException e) {
					log(new ErrorStatus(RJ_CLIENT_ID,
							"Communication error detail. Send:\n" + sendCom,
							e ));
					if (!this.closed && runAsyncPing()) { // async to avoid server gc
						if (this.consoleReadCallback == null && ok == 0) {
							ok++;
							handleStatus(new ErrorStatus(RJ_CLIENT_ID,
									"Communication error, see Eclipse log for detail." ),
									m );
							continue;
						}
						throw new StatusException(new ErrorStatus(RJ_CLIENT_ID,
								"Communication error.", e ));
					}
					handleServerStatus(new RjsStatus(RjsStatus.INFO, Server.S_LOST), m);
					return;
				}
			}
			
			handleServerStatus(new RjsStatus(RjsStatus.INFO, Server.S_DISCONNECTED), m);
		}
		finally {
			this.dataLevelIgnore= loopDataLevelIgnore;
		}
	}
	
	
	protected final void addC2SCmd(final MainCmdItem item) {
		if (this.mainC2SFirst == null) {
			this.mainC2SFirst= item;
		}
		else {
			item.next= this.mainC2SFirst;
			this.mainC2SFirst= item;
			
			// TODO
			log(new InfoStatus(RJ_CLIENT_ID,
					"Multiple C2S items:\\" + this.mainC2SFirst.toString() + "\n" + this.mainC2SFirst.next.toString() ));
		}
	}
	
	private final MainCmdItem getC2SCmds() {
		final MainCmdItem item= this.mainC2SFirst;
		this.mainC2SFirst= null;
		return item;
	}
	
	private final void processStatus(final RjsStatus status, final ProgressMonitor m)
			throws StatusException {
		if ((status.getCode() & 0xffffff00) == 0) {
			handleServerStatus(status, m);
			return;
		}
		if (status.getSeverity() != RjsStatus.OK) {
			// TODO
//			System.out.println(status);
		}
	}
	
	private final void processPrompt(final ConsoleReadCmdItem item) {
		switch (item.getCmdOption() & 0xf) {
		case 2:
			if (this.hotModeState < 2) {
				this.hotModeState= 2;
				this.hotModeReadCallbackBackup= this.consoleReadCallback;
				this.hotModeC2SFirstBackup= this.mainC2SFirst;
				this.mainC2SFirst= null;
			}
			this.consoleReadCallback= item;
			return;
		case RjsComObject.V_TRUE:
			this.consoleReadCallback= item;
			updatePrompt(item.getDataText(), true);
			return;
		default:
			this.consoleReadCallback= item;
			updatePrompt(item.getDataText(), false);
			return;
		}
	}
	
	public void requestHotMode(final boolean async) {
		this.hotModeRequested.set(true);
		if (async) {
			RJHelper_EXECUTOR.schedule(this.hotModeRunnable, 100, TimeUnit.MILLISECONDS);
		}
	}
	
	public boolean startHotMode() {
		if (this.hotModeState == 0) {
			this.hotModeRequested.set(false);
			final boolean savedCallbackRequired= this.consoleReadCallbackRequired;
			this.consoleReadCallbackRequired= false;
			try {
				this.hotModeState= 1;
				runMainLoop(new CtrlCmdItem(CtrlCmdItem.REQUEST_HOT_MODE), null,
						new NullProgressMonitor() );
				return true;
			}
			catch (final Throwable e) {
				this.hotModeState= 0;
				log(new ErrorStatus(RJ_CLIENT_ID,
						"An error occurred when running hot mode.",
						e ));
			}
			finally {
				this.consoleReadCallbackRequired= savedCallbackRequired;
			}
		}
		return false;
	}
	
	public void requestExtraMode(final int positions) {
		this.extraModeRequested= positions;
	}
	
	
	protected void updateBusy(final boolean isBusy) {
	}
	
	protected void updatePrompt(final String text, final boolean addToHistory) {
	}
	
	protected void writeConsoleOutput(final byte streamId, final String text) {
	}
	
	protected void showMessage(final String text) {
	}
	
	protected void processHotMode() {
	}
	
	protected void processExtraMode(final int i) {
	}
	
	private void addGraphic(final int devId, final double w, final double h, final int canvasColor,
			final boolean activate) throws RjException {
		if (devId >= 0) {
			if (devId >= this.graphics.length) {
				final RClientGraphic[] newArray= new RClientGraphic[devId + 10];
				System.arraycopy(this.graphics, 0, newArray, 0, this.graphics.length);
				this.graphics= newArray;
			}
			final InitConfig config= new InitConfig();
			config.canvasColor= canvasColor;
			if (this.graphics[devId] != null) {
				this.graphics[devId].reset(w, h, config);
				this.graphics[devId].setActive(activate);
			}
			else {
				this.graphics[devId]= this.lastGraphic= this.graphicFactory.newGraphic(devId,
						w, h, config,
						activate, this.graphicActions, this.currentGraphicOptions);
			}
			return;
		}
		throw new RjException("Invalid GD devId: " + devId);
	}
	
	private void removeGraphic(final int devId) {
		if (devId >= 0 && devId < this.graphics.length) {
			if (this.graphics[devId] != null) {
				try {
					this.graphicFactory.closeGraphic(this.graphics[devId]);
				}
				catch (final Exception e) {
					log(new ErrorStatus(RJ_CLIENT_ID,
							"An error occurred when closing R graphic (Device " + (devId+1) + ").",
							e ));
				}
				this.graphics[devId]= null;
			}
		}
	}
	
	protected RClientGraphic getGraphic(final int devId) {
		if (devId >= 0 && devId < this.graphics.length) {
			final RClientGraphic graphic= this.graphics[devId];
			if (graphic != null) {
				return graphic;
			}
		}
		return this.graphicDummy;
	}
	
	public void disposeAllGraphics() {
		for (int devId= 0; devId < this.graphics.length; devId++) {
			removeGraphic(devId);
		}
	}
	
	
	public final void activateConsole() {
		if (this.rjConsoleEngine == null) {
			throw new IllegalStateException("Missing REngine");
		}
		this.consoleReadCallbackRequired= true;
	}
	
	public final void answerConsole(final String input,
			final ProgressMonitor m) throws StatusException {
		this.consoleReadCallback.setAnswer(input);
		runMainLoop(null, this.consoleReadCallback, m);
		
		this.runFinishTask= false;
	}
	
	public final boolean isConsoleReady() {
		return (this.consoleReadCallback != null);
	}
	
	
	private Map<String, Object> getServerData() throws RemoteException {
		if (this.platformData != null) {
			return this.platformData;
		}
		final Map<String, Object> data= this.rjConsoleEngine.getPlatformData();
		if (data != null && data.containsKey("version.string")) { //$NON-NLS-1$
			this.platformData= data;
		}
		return data;
	}
	
	public final RPlatform getRPlatform() {
		synchronized (this.platformLock) {
			if (this.platformObj == null) {
				try {
					final Map<String, Object> data= getServerData();
					if (data != null && data.containsKey("version.string")) {
						this.platformObj= new RPlatform((String) this.platformData.get("os.type"),
								(String) this.platformData.get("file.sep"),
								(String) this.platformData.get("path.sep"),
								(String) this.platformData.get("version.string"),
								(String) this.platformData.get("os.name"),
								(String) this.platformData.get("os.arch"),
								(String) this.platformData.get("os.version") );
					}
				}
				catch (final RemoteException e) {
					log(new ErrorStatus(RJ_CLIENT_ID,
							"An error occured when loading data for RPlatform information.",
							e ));
				}
			}
			return this.platformObj;
		}
	}
	
	public final String getProperty(final String key) {
		synchronized (this.platformLock) {
			try {
				final Map<String, Object> data= getServerData();
				if (data != null) {
					final Object value= data.get(key);
					return (value instanceof String) ? (String) value : null;
				}
			}
			catch (final RemoteException e) {
			}
			return null;
		}
	}
	
	
	public final void finishTask(
			final ProgressMonitor m) throws StatusException {
		if (!this.runFinishTask) {
			return;
		}
		final int level= newDataLevel();
		try {
			runMainLoop(null, createDataRequestId(level, new MainCtrlCmdItem(MainCtrlCmdItem.OP_FINISH_TASK,
					0 )), m);
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Evaluation failed: %1$s");
			}
			return;
		}
		finally {
			finalizeDataLevel();
			this.runFinishTask= false;
		}
	}
	
	
	public boolean isValidEnvRef(final RObject envir) {
		switch (envir.getRObjectType()) {
		case RObject.TYPE_REFERENCE:
			return (((RReference) envir).getReferencedRObjectType() == RObject.TYPE_ENVIRONMENT);
		case RObject.TYPE_LANGUAGE:
			return true;
		default:
			return false;
		}
	}
	
	public final void evalVoid(final String expression, final @Nullable RObject envir,
			final ProgressMonitor m) throws StatusException {
		if (expression == null) {
			throw new NullPointerException("expression");
		}
		if (envir != null && !isValidEnvRef(envir)) {
			throw new IllegalArgumentException("envir");
		}
		final int level= newDataLevel();
		try {
			runMainLoop(null, createDataRequestId(level, new DataCmdItem(DataCmdItem.EVAL_EXPR_VOID,
					0, expression, null, null, envir )), m );
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Evaluation failed: %1$s");
			}
			return;
		}
		finally {
			finalizeDataLevel();
		}
	}
	
	public final void evalVoid(final String name, final RList args, final @Nullable RObject envir,
			final ProgressMonitor m) throws StatusException {
		if (name == null) {
			throw new NullPointerException("name");
		}
		if (args == null) {
			throw new NullPointerException("args");
		}
		if (envir != null && !isValidEnvRef(envir)) {
			throw new IllegalArgumentException("envir");
		}
		final int level= newDataLevel();
		try {
			runMainLoop(null, createDataRequestId(level, new DataCmdItem(DataCmdItem.EVAL_FCALL_VOID,
					0, name, args, null, envir )), m );
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Evaluation failed: %1$s");
			}
			return;
		}
		finally {
			finalizeDataLevel();
		}
	}
	
	public RObject evalData(final String expression, final @Nullable RObject envir,
			final @Nullable String factoryId, final int options, final int depth,
			final ProgressMonitor m) throws StatusException {
		if (expression == null) {
			throw new NullPointerException("expression");
		}
		if (envir != null && !isValidEnvRef(envir)) {
			throw new IllegalArgumentException("envir");
		}
		final byte checkedDepth= (depth < Byte.MAX_VALUE) ? (byte) depth : Byte.MAX_VALUE;
		final int level= newDataLevel();
		try {
			runMainLoop(null, createDataRequestId(level, new DataCmdItem(DataCmdItem.EVAL_EXPR_DATA,
					options, checkedDepth, expression, null, null, envir, factoryId )), m);
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Evaluation failed: %1$s");
			}
			return ((DataCmdItem) this.dataAnswer[level]).getData();
		}
		finally {
			finalizeDataLevel();
		}
	}
	
	public RObject evalData(final String name, final RObject args, final @Nullable RObject envir,
			final @Nullable String factoryId, final int options, final int depth,
			final ProgressMonitor m) throws StatusException {
		if (name == null) {
			throw new NullPointerException("name");
		}
		if (args == null) {
			throw new NullPointerException("args");
		}
		if (envir != null && !isValidEnvRef(envir)) {
			throw new IllegalArgumentException("envir");
		}
		final byte checkedDepth= (depth < Byte.MAX_VALUE) ? (byte) depth : Byte.MAX_VALUE;
		final int level= newDataLevel();
		try {
			runMainLoop(null, createDataRequestId(level, new DataCmdItem(DataCmdItem.EVAL_FCALL_DATA,
					options, checkedDepth, name, args, null, envir, factoryId )), m );
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Evaluation failed: %1$s");
			}
			return ((DataCmdItem) this.dataAnswer[level]).getData();
		}
		finally {
			finalizeDataLevel();
		}
	}
	
	public final RObject evalData(final RReference reference,
			final @Nullable String factoryId, final int options, final int depth,
			final ProgressMonitor m) throws StatusException {
		final byte checkedDepth= (depth < Byte.MAX_VALUE) ? (byte) depth : Byte.MAX_VALUE;
		final int level= newDataLevel();
		try {
			final long handle= reference.getHandle();
			runMainLoop(null, createDataRequestId(level, new DataCmdItem(DataCmdItem.RESOLVE_DATA,
					options, checkedDepth, Long.toString(handle), null, null, null, factoryId )), m );
			
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Evaluation failed: %1$s");
			}
			return ((DataCmdItem) this.dataAnswer[level]).getData();
		}
		finally {
			finalizeDataLevel();
		}
	}
	
	private StatusException toStatusException(final RjsStatus status, final String message) {
		return new StatusException((status.getSeverity() == RjsStatus.CANCEL) ?
				Status.CANCEL_STATUS :
				Status.newStatus(status.getSeverity(), RJ_CLIENT_ID, status.getCode(),
						String.format(message, status.getMessage()),
						null ));
	}
	
	public RObject evalData(final byte envType, final String name,
			final @Nullable String factoryId, final int options, final int depth,
			final ProgressMonitor m) throws StatusException {
		if (name == null) {
			throw new NullPointerException("name");
		}
		final Operation operation;
		switch (envType) {
		case REnvironment.ENVTYPE_NAMESPACE:
			operation= DataCmdItem.EVAL_NAMESPACE_DATA;
			break;
		case REnvironment.ENVTYPE_NAMESPACE_EXPORTS:
			operation= DataCmdItem.EVAL_NAMESPACE_EXPORTS_DATA;
			break;
		default:
			throw new IllegalArgumentException("envType= " + envType);
		}
		
		final byte checkedDepth= (depth < Byte.MAX_VALUE) ? (byte) depth : Byte.MAX_VALUE;
		final int level= newDataLevel();
		try {
			runMainLoop(null, createDataRequestId(level, new DataCmdItem(operation,
					options, checkedDepth,
					name, null, null, null, factoryId )), m );
			
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Evaluation failed: %1$s");
			}
			return ((DataCmdItem) this.dataAnswer[level]).getData();
		}
		finally {
			finalizeDataLevel();
		}
	}
	
	public final void assignData(final String expression, final RObject data, final @Nullable RObject envir,
			final ProgressMonitor m) throws StatusException {
		if (expression == null) {
			throw new NullPointerException("expression");
		}
		if (data == null) {
			throw new NullPointerException("data");
		}
		if (envir != null && !isValidEnvRef(envir)) {
			throw new IllegalArgumentException("envir");
		}
		final int level= newDataLevel();
		try {
			runMainLoop(null, createDataRequestId(level, new DataCmdItem(DataCmdItem.ASSIGN_DATA,
					0, null, data, expression, envir )), m );
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Assignment failed: %1$s");
			}
			return;
		}
		finally {
			finalizeDataLevel();
		}
	}
	
	public final void assignData(final String name, final RObject args, final String expression,
			final @Nullable RObject envir,
			final ProgressMonitor m) throws StatusException {
		if (name == null) {
			throw new NullPointerException("name");
		}
		if (args == null) {
			throw new NullPointerException("args");
		}
		if (expression == null) {
			throw new NullPointerException("expression");
		}
		if (envir != null && !isValidEnvRef(envir)) {
			throw new IllegalArgumentException("envir");
		}
		final int level= newDataLevel();
		try {
			runMainLoop(null, createDataRequestId(level, new DataCmdItem(DataCmdItem.ASSIGN_FCALL,
					0, name, args, expression, envir )), m );
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Assignment failed: %1$s");
			}
			return;
		}
		finally {
			finalizeDataLevel();
		}
	}
	
	public RObject[] findData(final String symbol, final RObject env, final boolean inherits,
			final @Nullable String factoryId, final int options, final int depth,
			final ProgressMonitor m) throws StatusException {
		if (symbol == null) {
			throw new NullPointerException("symbol");
		}
		final byte checkedDepth= (depth < Byte.MAX_VALUE) ? (byte) depth : Byte.MAX_VALUE;
		final int level= newDataLevel();
		try {
			runMainLoop(null, createDataRequestId(level, new DataCmdItem(DataCmdItem.FIND_DATA,
					(inherits) ? (options | 0x1000) : options, checkedDepth,
					symbol, null, null, env, factoryId )), m );
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Evaluation failed: %1$s");
			}
			final DataCmdItem dataItem= (DataCmdItem) this.dataAnswer[level];
			return (dataItem.getRho() != null) ?
					new RObject[] { dataItem.getData(), dataItem.getRho() } :
					null;
		}
		finally {
			finalizeDataLevel();
		}
	}
	
	
	public void downloadFile(final OutputStream out, final String fileName, final int options,
			final ProgressMonitor m) throws StatusException {
		final BinExchange request= new BinExchange(out, fileName, this.rjConsoleEngine, options);
		final BinExchange answer;
		try {
			answer= (BinExchange) runAsync(request);
		}
		finally {
			request.clear();
		}
		if (answer == null || !answer.isOK()) {
			final RjsStatus status= (answer != null) ? answer.getStatus() : MISSING_ANSWER_STATUS;
			throw toStatusException(status, "Downloading file failed: %1$s");
		}
	}
	
	public byte[] downloadFile(final String fileName, final int options,
			final ProgressMonitor m) throws StatusException {
		final BinExchange request= new BinExchange(fileName, this.rjConsoleEngine, options);
		final BinExchange answer;
		try {
			answer= (BinExchange) runAsync(request);
		}
		finally {
			request.clear();
		}
		if (answer == null || !answer.isOK()) {
			final RjsStatus status= (answer != null) ? answer.getStatus() : MISSING_ANSWER_STATUS;
			throw toStatusException(status, "Downloading file failed: %1$s");
		}
		return answer.getBytes();
	}
	
	public void uploadFile(final InputStream in, final long length, final String fileName, final int options,
			final ProgressMonitor m) throws StatusException {
		final BinExchange request= new BinExchange(in, length, fileName, this.rjConsoleEngine, options);
		final BinExchange answer;
		try {
			answer= (BinExchange) runAsync(request);
		}
		finally {
			request.clear();
		}
		if (answer == null || !answer.isOK()) {
			final RjsStatus status= (answer != null) ? answer.getStatus() : MISSING_ANSWER_STATUS;
			throw toStatusException(status, "Uploading file failed: %1$s");
		}
	}
	
	
	public Object execSyncDbgOp(final byte dbgOp, final RJIOExternalizable request,
			final ProgressMonitor m) throws StatusException {
		if (this.dbgOpRequest) {
			throw new IllegalStateException();
		}
		this.dbgOpRequest= true;
		try {
			runMainLoop(null, new DbgCmdItem(dbgOp, 0, request), m);
			if (this.dbgOpAnswer == null || !this.dbgOpAnswer.isOK()) {
				final RjsStatus status= (this.dbgOpAnswer != null) ? this.dbgOpAnswer.getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Dbg operation failed: %1$s");
			}
			{	final Object data= this.dbgOpAnswer.getData();
				if (data instanceof CtrlReport) {
					final CtrlReport report= (CtrlReport) data;
					if (!report.isEngineSuspended()) {
						this.consoleReadCallback= null;
					}
				}
				return data;
			}
		}
		finally {
			this.dbgOpRequest= false;
			this.dbgOpAnswer= null;
		}
	}
	
	public void execAsyncDbgOp(final byte op, final RJIOExternalizable request)
			throws StatusException {
		execAsync(new Runnable() {
			@Override
			public void run() {
				try {
					runAsync(new DbgCmdItem(op, 0, request));
					// in future check returned status if required
				}
				catch (final StatusException e) {
					log(new ErrorStatus(RJ_CLIENT_ID,
							"An error occurred when executing background dbg operation.",
							e ));
				}
			}
		});
	}
	
	
	public int getGraphicOptions() {
		return this.currentGraphicOptions;
	}
	
	public void setGraphicOptions(final int options) {
		this.currentGraphicOptions= options;
		this.lastGraphic= null;
	}
	
	public RClientGraphic getLastGraphic() {
		return this.lastGraphic;
	}
	
	public Object execSyncGraphicOp(final int devId, final byte op,
			final ProgressMonitor m) throws StatusException {
		final int level= newDataLevel();
		try {
			runMainLoop(null, createDataRequestId(level, new GraOpCmdItem(devId, op)),
					m );
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "Graphics operation failed: %1$s");
			}
			return ((GraOpCmdItem) this.dataAnswer[level]).getData();
		}
		finally {
			finalizeDataLevel();
		}
	}
	
	public Object execSyncGraphicOp(final int devId, final byte op, final RJIOExternalizable data,
			final ProgressMonitor m) throws StatusException {
		final int level= newDataLevel();
		try {
			runMainLoop(null, createDataRequestId(level, new GraOpCmdItem(devId, op, data)),
					m );
			if (this.dataAnswer[level] == null || !this.dataAnswer[level].isOK()) {
				final RjsStatus status= (this.dataAnswer[level] != null) ? this.dataAnswer[level].getStatus() : MISSING_ANSWER_STATUS;
				throw toStatusException(status, "\"Graphics operation failed: %1$s");
			}
			return ((GraOpCmdItem) this.dataAnswer[level]).getData();
		}
		finally {
			finalizeDataLevel();
		}
	}
	
	
	public void addCancelHandler(final Callable<Boolean> handler) {
		synchronized (this.cancelHandler) {
			this.cancelHandler.add(handler);
		}
	}
	
	public void removeCancelHandler(final Callable<Boolean> handler) {
		synchronized (this.cancelHandler) {
			final int idx= this.cancelHandler.lastIndexOf(handler);
			if (idx >= 0) {
				this.cancelHandler.remove(idx);
			}
		}
	}
	
	protected Callable<Boolean>[] getCancelHandlers() {
		synchronized (this.cancelHandler) {
			return this.cancelHandler.toArray(new Callable[this.cancelHandler.size()]);
		}
	}
	
	public Lock getWaitLock() {
		return this.clientWaitLock;
	}
	
	public void waitingForUser() {
		if (this.hotModeRequested.get()) {
			this.clientWaitLock.unlock();
			try {
				startHotMode();
			}
			finally {
				this.clientWaitLock.lock();
			}
			return;
		}
		
		try {
			this.clientWaitCondition.awaitNanos(1000 * 100);
		}
		catch (final InterruptedException e1) {
		}
	}
	
	public void resume() {
		this.clientWaitCondition.signal();
	}
	
}
