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

package org.eclipse.statet.internal.rj.eclient.graphics;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IPreferencesService;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.statushandlers.StatusManager;

import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet;
import org.eclipse.statet.jcommons.collections.ImCollections;

import org.eclipse.statet.ecommons.runtime.core.StatusChangeListener;
import org.eclipse.statet.ecommons.ts.core.Tool;
import org.eclipse.statet.ecommons.ui.util.UIAccess;

import org.eclipse.statet.internal.rj.eclient.graphics.FontManager.FontFamily;
import org.eclipse.statet.rj.eclient.graphics.DefaultGCRenderer;
import org.eclipse.statet.rj.eclient.graphics.ERGraphic;
import org.eclipse.statet.rj.eclient.graphics.ERGraphicInstruction;
import org.eclipse.statet.rj.eclient.graphics.LocatorCallback;
import org.eclipse.statet.rj.eclient.graphics.RGraphics;
import org.eclipse.statet.rj.eclient.graphics.comclient.ToolRClientGraphicActions;
import org.eclipse.statet.rj.eclient.graphics.util.CopyToDevRunnable;
import org.eclipse.statet.rj.graphic.core.RGraphicInitialization;
import org.eclipse.statet.rj.graphic.core.RGraphicInstruction;
import org.eclipse.statet.rj.graphic.core.util.CachedMapping;
import org.eclipse.statet.rj.graphic.core.util.CharMapping;
import org.eclipse.statet.rj.graphic.core.util.Unicode2AdbSymbolMapping;
import org.eclipse.statet.rj.server.client.RClientGraphic;
import org.eclipse.statet.rj.server.client.RClientGraphicFactory;
import org.eclipse.statet.rj.services.RService;
import org.eclipse.statet.rj.services.RServiceControlExtension;


/**
 * R graphic implementation of this plug-in. Implements R side API ({@link RClientGraphic})
 * as well as client side API ({@link ERGraphic}, {@link org.eclipse.statet.rj.graphic.core.RGraphic}).
 */
public class EclipseRGraphic implements RClientGraphic, ERGraphic {
	
	
	private static final CharMapping ADBSYMBOL_MAPPING= new CachedMapping(
			new Unicode2AdbSymbolMapping() );
	
	private static final long MILLI_NANOS= 1000000L;
	
	private static final int DIRECT_RED_MASK=   0x0000FF00;
	private static final int DIRECT_GREEN_MASK= 0x00FF0000;
	private static final int DIRECT_BLUE_MASK=  0xFF000000;
	private static final PaletteData DIRECT_PALETTE= new PaletteData(
			DIRECT_RED_MASK, DIRECT_GREEN_MASK, DIRECT_BLUE_MASK );
	
	private static final LocatorCallback R_LOCATOR_CALLBACK= new LocatorCallback() {
		
		@Override
		public String getMessage() {
			return "→ Locate a point by mouse click (request from R)";
		}
		
		@Override
		public int located(final double x, final double y) {
			return NEXT;
		}
		
		@Override
		public void stopped(final String type) {
		}
		
	};
	
	
	private static void disposeElements(final ERGraphicInstruction[] instructions,
			final int beginIdx, final int endIdx) {
		try {
			for (int i= beginIdx; i < endIdx; i++) {
				switch (instructions[i].getInstructionType()) {
				case RGraphicInstruction.DRAW_RASTER: {
					final Image image= ((RasterElement) instructions[i]).swtImage;
					if (image != null && !image.isDisposed()) {
						image.dispose();
					}
					continue; }
				case RGraphicInstruction.DRAW_PATH: {
					final Path path= ((PathElement) instructions[i]).swtPath;
					if (path != null && !path.isDisposed()) {
						path.dispose();
					}
					continue; }
				default:
					continue;
				}
			}
		}
		catch (final SWTException e) {
			if (e.code != SWT.ERROR_DEVICE_DISPOSED) {
				StatusManager.getManager().handle(new Status(IStatus.ERROR, RGraphics.BUNDLE_ID,
						"An error occurred when disposing SWT resources.", e ));
			}
		}
	}
	
	private static class DisposeRunnable implements Runnable {
		
		private final ERGraphicInstruction[] instructions;
		private final int size;
		
		private boolean delay;
		
		public DisposeRunnable(final ERGraphicInstruction[] instructions, final int size) {
			this.instructions= instructions;
			this.size= size;
		}
		
		@Override
		public void run() {
			if (this.delay) {
				this.delay= false;
				Display.getCurrent().timerExec(5000, this);
			}
			
			disposeElements(this.instructions, 0, this.size);
		}
		
	}
	
	
	private final int devId;
	
	private int canvasColor;
	
	private int drawingStopDelay= 33; // ms after stop
	private int drawingForceDelay= 333; // ms after last update
	
	private final EclipseRGraphicFactory manager;
	private boolean isRClosed;
	private boolean isLocalClosed;
	
	private final Object stateLock= new Object();
	private boolean isActive;
	private boolean isActiveNotified;
	private int mode= 1;
	private int modeNotified;
	private long drawingStoppedStamp;
	private long instructionsNotifiedStamp;
	private boolean stateNotificationDirectScheduled;
	private boolean stateNotificationDelayedScheduled;
	private final Runnable stateNotificationRunnable= new Runnable() {
		@Override
		public void run() {
			int type= 0;
			Runnable runnable= null;
			try {
				while (true) {
					boolean reset= false;
					List<ERGraphicInstruction> update= null;
					synchronized (EclipseRGraphic.this.stateLock) {
						if (type == 0
								&& !EclipseRGraphic.this.stateNotificationDirectScheduled
								&& EclipseRGraphic.this.stateNotificationDelayedScheduled) {
							EclipseRGraphic.this.stateNotificationDirectScheduled= true;
							EclipseRGraphic.this.stateNotificationDelayedScheduled= false;
						}
						if (EclipseRGraphic.this.isActive != EclipseRGraphic.this.isActiveNotified) {
							EclipseRGraphic.this.isActiveNotified= EclipseRGraphic.this.isActive;
							type= (EclipseRGraphic.this.isActive) ? 1 : 2;
						}
						else if ((EclipseRGraphic.this.mode == 1 || EclipseRGraphic.this.instructionsUpdateSize > 0)
								&& EclipseRGraphic.this.modeNotified != 1 ) {
							// start
							EclipseRGraphic.this.modeNotified= 1;
							type= 3;
						}
						else if (EclipseRGraphic.this.instructionsUpdateSize > 0) {
							// update
							final long stamp= System.nanoTime();
							int t= EclipseRGraphic.this.drawingForceDelay - (int) ((stamp - EclipseRGraphic.this.instructionsNotifiedStamp) / MILLI_NANOS);
							if (t > 10 && EclipseRGraphic.this.mode != 1) {
								t= Math.min(t, EclipseRGraphic.this.drawingStopDelay - (int) ((stamp - EclipseRGraphic.this.drawingStoppedStamp) / MILLI_NANOS));
							}
							if (t <= 10) {
								reset= (EclipseRGraphic.this.instructionsUpdateStart == 0);
								
								synchronized (EclipseRGraphic.this.instructionsLock) {
									if (reset && EclipseRGraphic.this.instructionsSize > 0) {
										runnable= new DisposeRunnable(EclipseRGraphic.this.instructions, EclipseRGraphic.this.instructionsSize);
									}
									EclipseRGraphic.this.instructions= EclipseRGraphic.this.instructionsUpdate;
									EclipseRGraphic.this.instructionsSize= EclipseRGraphic.this.instructionsUpdateStart + EclipseRGraphic.this.instructionsUpdateSize;
								}
								update= ImCollections.newList(EclipseRGraphic.this.instructionsUpdate)
										.subList(EclipseRGraphic.this.instructionsUpdateStart, EclipseRGraphic.this.instructionsUpdateStart + EclipseRGraphic.this.instructionsUpdateSize);
//								System.out.println("InstrUpdate: \treset= " + reset + " \tcount= " + update.size() + " \ttdiff= " + ((stamp - this.instructionsNotifiedStamp) / MILLI_NANOS));
								EclipseRGraphic.this.instructionsUpdateStart= EclipseRGraphic.this.instructionsSize;
								EclipseRGraphic.this.instructionsUpdateSize= 0;
								EclipseRGraphic.this.instructionsNotifiedStamp= stamp;
								type= 5;
							}
							else {
								if (!EclipseRGraphic.this.stateNotificationDelayedScheduled) {
									EclipseRGraphic.this.stateNotificationDelayedScheduled= true;
									EclipseRGraphic.this.display.timerExec(10 + Math.min(t, EclipseRGraphic.this.drawingStopDelay), this);
								}
								EclipseRGraphic.this.stateNotificationDirectScheduled= false;
								type= 0;
								return;
							}
						}
						else if (EclipseRGraphic.this.mode != 1 && EclipseRGraphic.this.modeNotified == 1 ) {
							// stop
							final long stamp= System.nanoTime();
							final int t= EclipseRGraphic.this.drawingStopDelay - (int) ((stamp - EclipseRGraphic.this.drawingStoppedStamp) / MILLI_NANOS);
							if (t <= 10) {
								EclipseRGraphic.this.modeNotified= 0;
								type= 4;
							}
							else {
								if (!EclipseRGraphic.this.stateNotificationDelayedScheduled) {
									EclipseRGraphic.this.stateNotificationDelayedScheduled= true;
									EclipseRGraphic.this.display.timerExec(10 + t, this);
								}
								EclipseRGraphic.this.stateNotificationDirectScheduled= false;
								type= 0;
								return;
							}
						}
						else {
							// done
							EclipseRGraphic.this.stateNotificationDirectScheduled= false;
							type= 0;
							return;
						}
					}
					
					
					switch (type) {
					case 1:
						for (final Listener listener : EclipseRGraphic.this.graphicListeners.toList()) {
							listener.activated();
						}
						break;
					case 2:
						for (final Listener listener : EclipseRGraphic.this.graphicListeners.toList()) {
							listener.deactivated();
						}
						break;
					case 3:
						for (final Listener listener : EclipseRGraphic.this.graphicListeners.toList()) {
							listener.drawingStarted();
						}
						break;
					case 4:
						for (final Listener listener : EclipseRGraphic.this.graphicListeners.toList()) {
							listener.drawingStopped();
						}
						break;
					case 5:
						for (final Listener listener : EclipseRGraphic.this.graphicListeners.toList()) {
							if (listener instanceof ListenerInstructionsExtension) {
								((ListenerInstructionsExtension) listener).instructionsChanged(reset, update);
							}
						}
//						System.out.println("InstrNotif: ns= " + (System.nanoTime() - this.instructionsNotifiedStamp));
						break;
					}
				}
			}
			finally {
				if (type != 0) {
					synchronized (EclipseRGraphic.this.stateLock) {
						EclipseRGraphic.this.stateNotificationDirectScheduled= false;
					}
				}
				if (runnable != null) {
					execInDisplay(runnable);
				}
			}
		}
	};
	
	
	private final int options;
	private final ToolRClientGraphicActions actions;
	private volatile double[] nextSize;
	private double[] size;
	
	private FontFamily currentFontFamily;
	private int currentFontSize;
	private int currentFontStyle;
	private int currentFontRFace;
	private CharMapping currentFontMapping;
	
	private String lastStringEnc;
	private double[] lastStringWidth;
	
	private final Display display;
	private boolean isDisposed;
	private final FontManager swtFontManager;
	private final ColorManager swtColorManager;
	
	private String serifFontName;
	private String sansFontName;
	private String monoFontName;
	private String symbolFontName;
	private CharMapping symbolFontMapping;
	
	/** List of newly added instructions */
	private ERGraphicInstruction[] instructionsNew= new ERGraphicInstruction[1]; // initial init
	/** Count of newly added instructions in {@link #instructionsNew} */
	private int instructionsNewSize;
	/** Current list of instructions, notified + not yet notified */
	private ERGraphicInstruction[] instructionsUpdate;
	/** Index of first not yet notified instruction in {@link #instructionsUpdate} */
	private int instructionsUpdateStart;
	/** Count of not yet notified instructions in {@link #instructionsUpdate} */
	private int instructionsUpdateSize;
	/** Lock for {@link #instructions} and {@link #instructionsSize} */
	private final Object instructionsLock= new Object();
	/** List of notified instructions */
	private ERGraphicInstruction[] instructions;
	/** Count of notified instructions in {@link #instructions} */
	private int instructionsSize;
	
	private final Object userExchangeLock= new Object();
	private String userExchangeRType;
	private RServiceControlExtension userExchangeRCallback;
	
	private volatile LocatorCallback locatorCallback; // != null => started
	private LocatorCallback locatorNotified;
	private IStatus locatorMessage;
	private Collection<String> locatorStopTypes= Collections.emptySet();
	private double[] locatorLocationValue; // only used for R
	private final Object locatorAnswerLock= new Object(); // pipe for answers
	
	private final CopyOnWriteIdentityListSet<ERGraphic.Listener> graphicListeners= new CopyOnWriteIdentityListSet<>();
	
	private IStatus message= Status.OK_STATUS;
	private final CopyOnWriteIdentityListSet<StatusChangeListener> messageListeners= new CopyOnWriteIdentityListSet<>();
	
	private boolean locatorNotificationDirectScheduled;
	private boolean locatorNotificationDeferredScheduled;
	private long locatorDeferredStamp;
	private final Runnable locatorNotificationRunnable= new Runnable() {
		@Override
		public void run() {
			int type= 0;
			try {
				while (true) {
					synchronized (EclipseRGraphic.this.userExchangeLock) {
						if (type == 0
								&& !EclipseRGraphic.this.locatorNotificationDirectScheduled
								&& EclipseRGraphic.this.locatorNotificationDeferredScheduled) {
							EclipseRGraphic.this.locatorNotificationDirectScheduled= true;
							EclipseRGraphic.this.locatorNotificationDeferredScheduled= false;
						}
						if (EclipseRGraphic.this.locatorCallback != null && EclipseRGraphic.this.locatorNotified == null
								&& EclipseRGraphic.this.locatorDeferredStamp == Long.MIN_VALUE) {
							EclipseRGraphic.this.locatorNotified= EclipseRGraphic.this.locatorCallback;
							type= 1;
						}
						else if (EclipseRGraphic.this.locatorNotified != null
								&& (EclipseRGraphic.this.locatorCallback != EclipseRGraphic.this.locatorNotified || EclipseRGraphic.this.locatorCallback == null) ){
							EclipseRGraphic.this.locatorNotified= null;
							type= 2;
						}
						else if (EclipseRGraphic.this.locatorDeferredStamp != Long.MIN_VALUE
								&& EclipseRGraphic.this.locatorCallback != null) {
							final int t= (int) ((EclipseRGraphic.this.locatorDeferredStamp - System.nanoTime()) / 1000000);
							if (t <= 10) {
								internalStopLocator(false);
								type= 3;
								continue;
							}
							else {
								if (!EclipseRGraphic.this.locatorNotificationDeferredScheduled) {
									EclipseRGraphic.this.locatorNotificationDeferredScheduled= true;
									EclipseRGraphic.this.display.timerExec(t + 10, this);
								}
								EclipseRGraphic.this.locatorNotificationDirectScheduled= false;
								type= 0;
								return;
							}
						}
						else {
							EclipseRGraphic.this.locatorNotificationDirectScheduled= false;
							type= 0;
							return;
						}
					}
					
					switch (type) {
					case 1:
						for (final Listener listener : EclipseRGraphic.this.graphicListeners.toList()) {
							if (listener instanceof ListenerLocatorExtension) {
								((ListenerLocatorExtension) listener).locatorStarted();
							}
						}
						break;
					case 2:
						for (final Listener listener : EclipseRGraphic.this.graphicListeners.toList()) {
							if (listener instanceof ListenerLocatorExtension) {	
								((ListenerLocatorExtension) listener).locatorStopped();
							}
						}
						break;
					}
					updateMessage();
				}
			}
			finally {
				if (type != 0) {
					synchronized (EclipseRGraphic.this.userExchangeLock) {
						EclipseRGraphic.this.locatorNotificationDirectScheduled= false;
					}
				}
			}
		}
	};
	
	
	public EclipseRGraphic(final int devId, final double w, final double h, final InitConfig config,
			final boolean active, final ToolRClientGraphicActions actions, final int options,
			final EclipseRGraphicFactory manager) {
		this.devId= devId;
		this.isActive= active;
		this.actions= actions;
		this.manager= manager;
		this.options= options;
		
		this.display= UIAccess.getDisplay();
		this.swtFontManager= manager.getFontManager(this.display);
//		this.swtFontManager= new FontManager(this.display); // -> dispose!
		this.swtColorManager= manager.getColorManager(this.display);
		
		this.size= this.nextSize= new double[] { w, h };
		initPanel(w, h, config);
	}
	
	
	@Override
	public String getLabel() {
		final StringBuilder sb= new StringBuilder();
		sb.append("Device ");
		sb.append(this.devId + 1);
		if (this.actions != null) {
			final String rLabel= this.actions.getRLabel();
			if (rLabel != null && rLabel.length() > 0) {
				sb.append(" │ ");
				sb.append(rLabel);
			}
		}
		final boolean locator= isLocatorStarted();
		if (this.isActive || locator) {
			sb.append(" \t<"); //$NON-NLS-1$
			if (this.isActive) {
				sb.append("active+"); //$NON-NLS-1$
			}
			if (locator) {
				sb.append("locator+"); //$NON-NLS-1$
			}
			sb.replace(sb.length()-1, sb.length(), ">"); //$NON-NLS-1$
		}
		return sb.toString();
	}
	
	private void add(final ERGraphicInstruction instr) {
		// adding is always in R thread
		if (this.instructionsNew == null) {
			this.instructionsNew= new ERGraphicInstruction[512];
		}
		else if (this.instructionsNewSize >= this.instructionsNew.length) {
			final ERGraphicInstruction[] newArray= new ERGraphicInstruction[this.instructionsNewSize + 512];
//			System.out.println("NewArray " + this.instructionsNewSize + " -> " + newArray.length);
			System.arraycopy(this.instructionsNew, 0, newArray, 0, this.instructionsNewSize);
			this.instructionsNew= newArray;
		}
		this.instructionsNew[this.instructionsNewSize]= instr;
		this.instructionsNewSize++;
	}
	
	protected void initPanel(final double w, final double h, final InitConfig config) {
		this.drawingStopDelay= 33;
		this.drawingForceDelay= 333;
		
		this.currentFontFamily= null;
		this.currentFontMapping= null;
		
		final IPreferencesService preferences= Platform.getPreferencesService();
		this.serifFontName= preferences.getString(RGraphics.FONTS_PREF_QUALIFIER, RGraphics.PREF_FONTS_SERIF_FONTNAME_KEY, "", null);
		this.sansFontName= preferences.getString(RGraphics.FONTS_PREF_QUALIFIER, RGraphics.PREF_FONTS_SANS_FONTNAME_KEY, "", null);
		this.monoFontName= preferences.getString(RGraphics.FONTS_PREF_QUALIFIER, RGraphics.PREF_FONTS_MONO_FONTNAME_KEY, "", null);
		if (preferences.getBoolean(RGraphics.FONTS_PREF_QUALIFIER, RGraphics.PREF_FONTS_SYMBOL_USE_KEY, true, null)) {
			this.symbolFontName= preferences.getString(RGraphics.FONTS_PREF_QUALIFIER, RGraphics.PREF_FONTS_SYMBOL_FONTNAME_KEY, "Symbol", null); //$NON-NLS-1$
			final String encoding= preferences.getString(RGraphics.FONTS_PREF_QUALIFIER, RGraphics.PREF_FONTS_SYMBOL_ENCODING_KEY, "AdobeSymbol", null); //$NON-NLS-1$
			if ("AdobeSymbol".equals(encoding)) { //$NON-NLS-1$
				this.symbolFontMapping= ADBSYMBOL_MAPPING;
			}
			else {
				this.symbolFontMapping= null;
			}
		}
		else {
			this.symbolFontName= null;
			this.symbolFontMapping= null;
		}
		this.canvasColor= (config.canvasColor & 0xffffff);
		
		add(new GraphicInitialization(w, h, this.canvasColor, this.swtColorManager.getColor(this.canvasColor)));
	}
	
	@Override
	public void reset(final double w, final double h, final InitConfig config) {
		synchronized (this.stateLock) {
			internalReset();
		}
		
		initPanel(w, h, config);
	}
	
	private void internalReset() {
		if (this.instructionsNew != null) {
			if (this.instructionsNewSize > 0) {
				disposeElements(this.instructionsNew, 0, this.instructionsNewSize);
			}
			this.instructionsNew= null;
			this.instructionsNewSize= 0;
		}
		if (this.instructionsUpdate != null) {
			if (this.instructionsUpdateSize > 0) {
				disposeElements(this.instructionsUpdate, this.instructionsUpdateStart, this.instructionsUpdateStart+this.instructionsUpdateSize);
			}
			this.instructionsUpdate= null;
			this.instructionsUpdateStart= 0;
			this.instructionsUpdateSize= 0;
		}
		this.drawingStoppedStamp= System.nanoTime();
		this.instructionsNotifiedStamp= this.drawingStoppedStamp - 1000 * MILLI_NANOS;
	}
	
	private void execInDisplay(final Runnable runnable) {
		try {
			this.display.asyncExec(runnable);
		}
		catch (final SWTException e) {
			if (e.code != SWT.ERROR_DEVICE_DISPOSED) {
				throw e;
			}
		}
	}
	
	@Override
	public int getDevId() {
		return this.devId;
	}
	
	@Override
	public void setActive(final boolean active) {
		if (this.isActive == active) {
			return;
		}
		synchronized (this.stateLock) {
			this.isActive= active;
			if (this.isDisposed) {
				return;
			}
			if (!this.stateNotificationDirectScheduled) {
				this.stateNotificationDirectScheduled= true;
				execInDisplay(this.stateNotificationRunnable);
			}
		}
	}
	
	@Override
	public boolean isActive() {
		return this.isActive;
	}
	
	@Override
	public void setMode(final int mode) {
		synchronized (this.stateLock) {
			if (this.mode == mode) {
				return;
			}
			if (mode != 1) {
				this.drawingStoppedStamp= System.nanoTime();
				flushNewInstructions();
			}
			this.mode= mode;
			if (this.isDisposed) {
				return;
			}
			if (mode == 1 && this.modeNotified != 1 // need start
					&& !this.stateNotificationDirectScheduled ) {
				this.stateNotificationDirectScheduled= true;
				execInDisplay(this.stateNotificationRunnable);
			}
			else if (mode != 1 // stop
					&& !(this.stateNotificationDirectScheduled || this.stateNotificationDelayedScheduled) ) {
				this.stateNotificationDirectScheduled= true;
				execInDisplay(this.stateNotificationRunnable);
			}
		}
	}
	
	private void flushNewInstructions() {
		if (this.instructionsNewSize > 0) {
			if (this.instructionsUpdate == null) {
				this.instructionsUpdate= this.instructionsNew;
				this.instructionsUpdateStart= 0;
				this.instructionsUpdateSize= this.instructionsNewSize;
				this.instructionsNew= null;
				this.instructionsNewSize= 0;
			}
			else {
				final int newSize= this.instructionsUpdateStart + this.instructionsUpdateSize + this.instructionsNewSize;
				if (newSize > this.instructionsUpdate.length) {
					final ERGraphicInstruction[] newArray= new ERGraphicInstruction[newSize + 512];
					System.arraycopy(this.instructionsUpdate, 0, newArray, 0, this.instructionsUpdateStart + this.instructionsUpdateSize);
					this.instructionsUpdate= newArray;
				}
				System.arraycopy(this.instructionsNew, 0, this.instructionsUpdate, this.instructionsUpdateStart + this.instructionsUpdateSize, this.instructionsNewSize);
				this.instructionsUpdateSize+= this.instructionsNewSize;
				this.instructionsNewSize= 0;
			}
		}
	}
	
	private List<ERGraphicInstruction> getCurrentInstructions() {
		synchronized (this.stateLock) {
			flushNewInstructions();
			return ImCollections.newList(this.instructionsUpdate).subList(0,
					this.instructionsSize + this.instructionsUpdateSize );
		}
	}
	
	@Override
	public double[] computeSize() {
		return this.size;
	}
	
	
	protected void printFont() {
		System.out.println(this.currentFontFamily.name + " " + this.currentFontStyle + " " + this.currentFontSize);
	}
	
	@Override
	public double[] computeFontMetric(final int ch) {
//		System.out.println("==\nTextMetrics: \"" + ((char) ch) + "\" (" + ch + ")"); printFont();
		return this.currentFontFamily.getCharMetrics(this.currentFontStyle, this.currentFontSize,
				(this.currentFontMapping != null) ? this.currentFontMapping.encode(ch) : ch );
	}
	
	@Override
	public double[] computeStringWidth(final String txt) {
//		System.out.println("==\nTextWidth: \"" + txt + "\""); printFont();
		return computeStringWidthEnc((this.currentFontMapping != null) ? this.currentFontMapping.encode(txt) : txt);
	}
	
	protected final double[] computeStringWidthEnc(final String text) {
		if (text.equals(this.lastStringEnc)) {
			return this.lastStringWidth;
		}
		
		final double[] answer= this.currentFontFamily.getStringWidth(this.currentFontStyle, this.currentFontSize, text);
		
		this.lastStringEnc= text;
		return (this.lastStringWidth= answer);
	}
	
	
	@Override
	public void addSetClip(final double x0, final double y0, final double x1, final double y1) {
		final ClipSetting instr= new ClipSetting(x0, y0, x1, y1);
		add(instr);
	}
	
	@Override
	public void addSetColor(final int color) {
		final ColorSetting instr= new ColorSetting(color,
				this.swtColorManager.getColor((color & 0xffffff)) );
		add(instr);
	}
	
	@Override
	public void addSetFill(final int color) {
		final FillSetting instr= new FillSetting(color,
				this.swtColorManager.getColor((color & 0xffffff)) );
		add(instr);
	}
	
	@Override
	public void addSetFont(String family, final int face, final float pointSize,
			final float lineHeight) {
//		System.out.println("==\nSetFont: \"" + family + "\" " + face + " " + pointSize);
		switch (face) {
		case 2:
		case 3:
		case 4:
			family= getFontName(family);
			this.currentFontStyle= face - 1;
			this.currentFontMapping= null;
			break;
		case 5:
			if (this.symbolFontName != null) {
				family= this.symbolFontName;
				this.currentFontStyle= 0;
				this.currentFontMapping= this.symbolFontMapping;
				break;
			}
			//$FALL-THROUGH$
		default:
			family= getFontName(family);
			this.currentFontStyle= 0;
			this.currentFontMapping= null;
			break;
		}
		this.currentFontFamily= this.swtFontManager.getFamily(family);
		this.currentFontRFace= face;
		this.currentFontSize= (int) (pointSize + 0.5);
		
		this.lastStringEnc= null;
		
		final FontSetting instr= new FontSetting(family, face, pointSize, lineHeight,
				this.currentFontFamily.getSWTFont(this.currentFontStyle, this.currentFontSize),
				this.currentFontFamily.getSWTFontProperties(this.currentFontStyle, this.currentFontSize) );
		add(instr);
	}
	
	private String getFontName(final String family) {
		if (family.length() == 0 || family.equals("sansserif")) {
			return this.sansFontName;
		}
		else if (family.equals("serif")) {
			return this.serifFontName;
		}
		else if (family.equals("mono")) {
			return this.monoFontName;
		}
		else {
			return family;
		}
	}
	
	@Override
	public void addSetLine(final int type, final float width,
			final byte cap, final byte join, final float joinMiterLimit) {
		final LineSetting instr= new LineSetting(type, width, cap, join, joinMiterLimit);
		add(instr);
	}
	
	@Override
	public void addDrawLine(final double x0, final double y0, final double x1, final double y1) {
		final LineElement instr= new LineElement(x0, y0, x1, y1);
		add(instr);
	}
	
	@Override
	public void addDrawRect(final double x0, final double y0, final double x1, final double y1) {
		final RectElement instr= new RectElement(x0, y0, x1, y1);
		add(instr);
	}
	
	@Override
	public void addDrawPolyline(final double[] x, final double[] y) {
		final PolylineElement instr= new PolylineElement(x, y);
		add(instr);
	}
	
	@Override
	public void addDrawPolygon(final double[] x, final double[] y) {
		final PolygonElement instr= new PolygonElement(x, y);
		add(instr);
	}
	
	@Override
	public void addDrawPath(final int[] n, final double[] x, final double[] y, final int winding) {
		final Path path= new Path(this.display);
		int k= 0, end= 0;
		for (int i= 0; i < n.length; i++) {
			end+= n[i];
			path.moveTo((float) Math.floor(x[k] + 0.5), (float) Math.floor(y[k++] + 0.5));
			while (k < end) {
				path.lineTo((float) Math.floor(x[k] + 0.5), (float) Math.floor(y[k++] + 0.5));
			}
			path.close();
		}
		final PathElement instr= new PathElement(n, x, y, winding, path);
		add(instr);
	}
	
	@Override
	public void addDrawCircle(final double x, final double y, final double r) {
		final CircleElement instr= new CircleElement(x, y, r);
		add(instr);
	}
	
	@Override
	public void addDrawText(final String txt,
			final double x, final double y, final double rDeg, final double hAdj) {
//		System.out.println("==\nDrawText: " + x + ", " + y + " " + hAdj + " \"" + txt + "\""); printFont();
		final String text= (this.currentFontMapping != null) ? this.currentFontMapping.encode(txt) : txt;
		final TextElement instr= new TextElement(text, x, y, rDeg, hAdj,
				(hAdj != 0) ? computeStringWidthEnc(text)[0] : 0);
		add(instr);
	}
	
	@Override
	public void addDrawRaster(final byte[] imgData, final boolean hasAlpha,
			final int imgWidth, final int imgHeight,
			final double x, final double y, final double w, final double h,
			final double rDeg, final boolean interpolate) {
		final ImageData imageData= new ImageData(imgWidth, imgHeight, 32, DIRECT_PALETTE, 4, imgData);
		if (hasAlpha) {
			final byte[] alpha= new byte[imgWidth*imgHeight];
			for (int i= 0; i < alpha.length; i++) {
				alpha[i]= imgData[i*4 + 3];
			}
			imageData.alphaData= alpha;
		}
		final Image swtImage= new Image(this.display, imageData);
		final RasterElement instr= new RasterElement(imgData, imgWidth, imgHeight, x, y, w, h,
				rDeg, interpolate, swtImage );
		add(instr);
	}
	
	@Override
	public byte[] capture(final int width, final int height) {
		ImageData imageData;
		{	Image image= null;
			GC gc= null;
			try {
				image= new Image(this.display, width, height);
				gc= new GC(image);
				final DefaultGCRenderer renderer= new DefaultGCRenderer();
				final List<ERGraphicInstruction> instructions= getCurrentInstructions();
				if (instructions.isEmpty()) {
					return null;
				}
				{	final RGraphicInitialization init= (RGraphicInitialization) instructions.get(0);
					double scale;
					if (width == (int) (init.width + 0.5)) {
						scale= 1.0;
					}
					else {
						scale= width / init.width;
					}
					renderer.clear(scale);
				}
				renderer.paint(gc, instructions);
				gc.dispose();
				gc= null;
				imageData= image.getImageData();
				image.dispose();
				image= null;
			}
			finally {
				if (gc != null && !gc.isDisposed()) {
					gc.dispose();
				}
				if (image != null && !image.isDisposed()) {
					image.dispose();
				}
			}
		}
		if (imageData == null || !imageData.palette.isDirect) {
			return null;
		}
		if (imageData.palette.redMask != DIRECT_RED_MASK
				|| imageData.palette.greenMask != DIRECT_GREEN_MASK
				|| imageData.palette.blueMask != DIRECT_BLUE_MASK
				|| imageData.scanlinePad != 4
				|| imageData.bytesPerLine != width * 4
				|| imageData.data.length != width * height * 4 ) {
			final byte[] data= (imageData.data.length == width * height * 4) ?
					imageData.data : new byte[width * height * 4];
			final int blueMask= imageData.palette.blueMask;
			final int blueShift= imageData.palette.blueShift;
			final int greenMask= imageData.palette.greenMask;
			final int greenShift= imageData.palette.greenShift;
			final int redMask= imageData.palette.redMask;
			final int redShift= imageData.palette.redShift;
			int i= 0;
			for (int y= 0; y < height; y++) {
				for (int x= 0; x < width; x++) {
					final int p= imageData.getPixel(x, y);
					data[i++]= (blueShift < 0) ?
							(byte) ((p & blueMask) >>> -blueShift) :
							(byte) ((p & blueMask) << blueShift);
					data[i++]= (greenShift < 0) ?
							(byte) ((p & greenMask) >>> -greenShift) :
							(byte) ((p & greenMask) << greenShift);
					data[i++]= (redShift < 0) ?
							(byte) ((p & redMask) >>> -redShift) :
							(byte) ((p & redMask) << redShift);
					data[i++]= (byte) 255;
				}
			}
			return data;
		}
		return imageData.data;
	}
	
	
	protected void waitRUserExchange(final String type, final RService r, final IProgressMonitor monitor,
			final Callable<Boolean> cancelListener) {
		final RServiceControlExtension rControl= (r instanceof RServiceControlExtension) ?
				(RServiceControlExtension) r : null;
		if (rControl != null && cancelListener != null) {
			rControl.addCancelHandler(cancelListener);
			rControl.getWaitLock().lock();
		}
		try {
			while (true) {
				synchronized (this.userExchangeLock) {
					if (this.userExchangeRType != type) {
						this.userExchangeRCallback= null;
						return;
					}
					if (this.isLocalClosed || this.isRClosed || monitor.isCanceled() ) {
						this.userExchangeRType= null;
						this.userExchangeRCallback= null;
						return;
					}
					this.userExchangeRCallback= rControl;
				}
				
				if (rControl != null) {
					rControl.waitingForUser(monitor);
				}
				else {
					try {
						Thread.sleep(50);
					}
					catch (final InterruptedException e) {
					}
				}
			}
		}
		finally {
			if (rControl != null && cancelListener != null) {
				rControl.getWaitLock().unlock();
				rControl.removeCancelHandler(cancelListener);
			}
		}
	}
	
	
	private void internalStartLocator(final LocatorCallback callback) {
		this.locatorCallback= callback;
		this.locatorMessage= new Status(IStatus.INFO, RGraphics.BUNDLE_ID, callback.getMessage());
		this.locatorStopTypes= callback.getStopTypes();
		this.locatorDeferredStamp= Long.MIN_VALUE;
		
		if (this.display.isDisposed()) {
			return;
		}
		if (!this.locatorNotificationDirectScheduled) {
			execInDisplay(this.locatorNotificationRunnable);
		}
	}
	
	private void internalStopLocator(final boolean deferred) {
		if (deferred) {
			this.locatorDeferredStamp= System.nanoTime() + 500 * MILLI_NANOS;
			if (this.display.isDisposed()) {
				return;
			}
			if (!(this.locatorNotificationDirectScheduled || this.locatorNotificationDeferredScheduled)) {
				this.locatorNotificationDirectScheduled= true;
				execInDisplay(this.locatorNotificationRunnable);
			}
			return;
		}
		
		this.locatorCallback= null;
		this.locatorMessage= null;
		this.locatorStopTypes= Collections.emptySet();
		this.locatorDeferredStamp= Long.MIN_VALUE;
		
		if (this.display.isDisposed()) {
			return;
		}
		if (!this.locatorNotificationDirectScheduled) {
			this.locatorNotificationDirectScheduled= true;
			execInDisplay(this.locatorNotificationRunnable);
		}
	}
	
	@Override
	public double[] runRLocator(final RService r, final IProgressMonitor monitor) {
		synchronized (this.userExchangeLock) {
			if (this.locatorCallback != null && this.locatorCallback != R_LOCATOR_CALLBACK) {
				return null;
			}
			this.userExchangeRType= "locator";
			internalStartLocator(R_LOCATOR_CALLBACK);
			
			this.locatorLocationValue= null;
		}
		waitRUserExchange("locator", r, monitor, new Callable<Boolean>() {
			@Override
			public Boolean call() {
				return Boolean.valueOf(answerLocator(null, null, true));
			}
		});
		final double[] value;
		synchronized (this.userExchangeLock) {
			value= this.locatorLocationValue;
			if (this.userExchangeRType == "locator") {
				this.userExchangeRType= null;
			}
			// avoid flickering as well as stale locators
			internalStopLocator(value != null);
		}
		return value;
	}
	
	@Override
	public IStatus startLocalLocator(final LocatorCallback callback) {
		if (callback == null) {
			throw new NullPointerException("callback"); //$NON-NLS-1$
		}
		synchronized (this.userExchangeLock) {
			if (this.locatorCallback != null && this.locatorCallback != callback) {
				return new Status(IStatus.ERROR, RGraphics.BUNDLE_ID, "Another locator is already started.");
			}
			internalStartLocator(callback);
		}
		return Status.OK_STATUS;
	}
	
	@Override
	public boolean isLocatorStarted() {
		return (this.locatorCallback != null);
	}
	
	@Override
	public Collection<String> getLocatorStopTypes() {
		return this.locatorStopTypes;
	}
	
	@Override
	public void returnLocator(final double x, final double y) {
		answerLocator(null, new double[] { x, y }, false);
	}
	
	@Override
	public void stopLocator(final String type) {
		answerLocator(type, null, false);
	}
	
	private boolean answerLocator(final String type, final double[] xy,
			final boolean onlyR) {
		synchronized (this.locatorAnswerLock) {
			RServiceControlExtension rControl= null;
			LocatorCallback callback;
			synchronized (this.userExchangeLock) {
				if (this.locatorCallback == null || this.locatorDeferredStamp != Long.MIN_VALUE) {
					return false;
				}
				if (this.locatorCallback == R_LOCATOR_CALLBACK) {
					if (this.userExchangeRType == "locator") { //$NON-NLS-1$
						this.userExchangeRType= null;
						rControl= this.userExchangeRCallback;
					}
					else {
						return false;
					}
				}
				else if (onlyR) {
					return false;
				}
				if (xy == null && type != null && !this.locatorStopTypes.contains(type)) {
					return false;
				}
				this.locatorLocationValue= xy;
				callback= this.locatorCallback;
			}
			
			final int code;
			if (callback == R_LOCATOR_CALLBACK) {
				if (xy != null) {
					code= -1;
				}
				else {
					code= LocatorCallback.STOP;
				}
				if (rControl != null) {
					rControl.getWaitLock().lock();
					try {
						rControl.resume();
					}
					finally {
						rControl.getWaitLock().unlock();
					}
				}
			}
			else {
				if (xy != null) {
					code= callback.located(xy[0], xy[1]);
				}
				else {
					code= LocatorCallback.STOP;
					callback.stopped(type);
				}
			}
			synchronized (this.userExchangeLock) {
				if (code == LocatorCallback.NEXT) {
					internalStartLocator(callback);
				}
				else {
					internalStopLocator((code == -1));
				}
			}
			return true;
		}
	}
	
	
	public void closeFromR() {
		this.isRClosed= true;
		if (this.isLocalClosed
				|| (this.options & RClientGraphicFactory.R_CLOSE_OFF) == 0) {
			dispose();
		}
		answerLocator(null, null, true);
		setActive(false);
	}
	
	protected void dispose() {
		this.graphicListeners.clear();
		Runnable runnable= null;
		synchronized (this.stateLock) {
			if (!this.isDisposed) {
				this.isDisposed= true;
				internalReset();
				synchronized (this.instructionsLock) {
					if (this.instructionsSize > 0) {
						runnable= new DisposeRunnable(this.instructions, this.instructionsSize);
					}
					this.instructionsSize= 0;
					this.instructions= null;
				}
			}
		}
		if (runnable != null) {
			execInDisplay(runnable);
		}
	}
	
	
	@Override
	public List<ERGraphicInstruction> getInstructions() {
		synchronized (this.instructionsLock) {
			return (this.instructionsSize > 0) ?
					ImCollections.newList(this.instructions).subList(0, this.instructionsSize) :
					ImCollections.<ERGraphicInstruction>emptyList();
		}
	}
	
	@Override
	public Tool getRHandle() {
		if (this.actions != null) {
			return this.actions.getRHandle();
		}
		return null;
	}
	
	@Override
	public IStatus resize(final double w, final double h) {
		if (this.actions != null) {
			this.nextSize= new double[] { w, h };
			return this.actions.resizeGraphic(this.devId, new Runnable() {
				@Override
				public void run() {
					EclipseRGraphic.this.size= EclipseRGraphic.this.nextSize;
				}
			});
		}
		return null;
	}
	
	@Override
	public IStatus close() {
		if (this.isRClosed) {
			this.isLocalClosed= true;
			dispose();
		}
		if (this.actions != null) {
			answerLocator(null, null, false);
			return this.actions.closeGraphic(this.devId);
		}
		else {
			this.isLocalClosed= true;
			answerLocator(null, null, false);
			this.manager.close(this);
			dispose();
		}
		return null;
	}
	
	@Override
	public void addListener(final Listener listener) {
		this.graphicListeners.add(listener);
	}
	
	@Override
	public void removeListener(final Listener listener) {
		this.graphicListeners.remove(listener);
	}
	
	protected void updateMessage() {
		IStatus message;
		if (this.locatorMessage != null) {
			message= this.locatorMessage;
		}
		else {
			message= Status.OK_STATUS;
		}
		if (!this.message.equals(message)) {
			this.message= message;
			for (final StatusChangeListener listener : this.messageListeners.toList()) {
				listener.statusChanged(message);
			}
		}
	}
	
	@Override
	public IStatus getMessage() {
		return this.message;
	}
	
	@Override
	public void addMessageListener(final StatusChangeListener listener) {
		this.messageListeners.add(listener);
	}
	
	@Override
	public void removeMessageListener(final StatusChangeListener listener) {
		this.messageListeners.remove(listener);
	}
	
	
	protected void preAction() throws CoreException {
		if (this.actions == null || this.actions.getRHandle() == null) {
			throw new UnsupportedOperationException();
		}
		if (this.isRClosed) {
			throw new CoreException(new Status(IStatus.ERROR, RGraphics.BUNDLE_ID,
					"The R graphic device is already closed." ));
		}
	}
	
	@Override
	@Deprecated
	public IStatus copy(final String toDev, final String toDevFile, final String toDevArgs)
			throws CoreException {
		preAction();
		return this.actions.getRHandle().getQueue().add(new CopyToDevRunnable(this,
				toDev, toDevFile, toDevArgs ));
	}
	
	@Override
	public void copy(final String toDev, final String toDevFile, final String toDevArgs,
			final IProgressMonitor monitor) throws CoreException {
		preAction();
		this.actions.copy(this.devId, toDev, toDevFile, toDevArgs, monitor);
	}
	
	@Override
	public double[] convertGraphic2User(final double[] xy,
			final IProgressMonitor monitor) throws CoreException {
		preAction();
		return this.actions.convertGraphic2User(this.devId, xy, monitor);
	}
	
	@Override
	public double[] convertUser2Graphic(final double[] xy,
			final IProgressMonitor monitor) throws CoreException {
		preAction();
		return this.actions.convertUser2Graphic(this.devId, xy, monitor);
	}
	
}
