/*=============================================================================#
 # Copyright (c) 2011, 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.eclient.graphics.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
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.ts.core.SystemRunnable;
import org.eclipse.statet.jcommons.ts.core.Tool;
import org.eclipse.statet.jcommons.ts.core.ToolService;

import org.eclipse.statet.rj.eclient.graphics.ERGraphic;
import org.eclipse.statet.rj.eclient.graphics.LocatorCallback;
import org.eclipse.statet.rj.ts.core.RTool;


/**
 * Basic implementation for a local locator for R graphics.
 * <p>
 * Requests the user to locate point and converts the graphic coordinates to user coordinates.
 * It uses the tool service API (org.eclipse.statet.jcommons.ts.core) to schedule the R job.</p>
 */
public abstract class AbstractLocalLocator extends LocatorCallback implements SystemRunnable {
	
	protected static final ImList<String> OK_CANCEL_STOP_TYPES= ImCollections.newList(
			ERGraphic.LOCATOR_DONE, ERGraphic.LOCATOR_CANCEL );
	
	
	private final ERGraphic graphic;
	private final RTool tool;
	
	private boolean started;
	private boolean graphicLocatorStarted;
	private boolean runnableScheduled;
	
	private final List<double[]> toConvert= new ArrayList<>();
	
	private final List<double[]> locatedGraphic= new ArrayList<>();
	private final List<double[]> locatedUser= new ArrayList<>();
	
	private volatile int counter;
	
	
	public AbstractLocalLocator(final ERGraphic graphic) {
		this.graphic= graphic;
		this.tool= graphic.getRHandle();
	}
	
	
	@Override
	public Collection<String> getStopTypes() {
		return OK_CANCEL_STOP_TYPES;
	}
	
	@Override
	public String getMessage() {
		return super.getMessage() + " (" + this.counter + " selected)";
	}
	
	@Override
	public int located(final double x, final double y) {
		synchronized (this) {
			this.counter++;
			this.toConvert.add(new double[] { x, y });
			if (!internalScheduleConversion()) {
				internalStop(null);
				return STOP;
			}
		}
		return NEXT;
	}
	
	@Override
	public void stopped(final String type) {
		synchronized (this) {
			this.graphicLocatorStarted= false;
			if (type == ERGraphic.LOCATOR_DONE) {
				if (this.toConvert.isEmpty()) {
					internalStop(ERGraphic.LOCATOR_DONE);
					return;
				}
				else if (internalScheduleConversion()) {
					return;
				}
				// scheduling failed
			}
			internalStop(null);
			return;
		}
	}
	
	@Override
	public String getTypeId() {
		return "r/rjgd/locallocator"; //$NON-NLS-1$
	}
	
	@Override
	public String getLabel() {
		return "Resolve Graphic Points";
	}
	
	@Override
	public boolean canRunIn(final Tool tool) {
		return (tool == this.tool);
	}
	
	@Override
	public boolean changed(final int event, final Tool tool) {
		switch (event) {
		case REMOVING_FROM:
			return false;
		case BEING_ABANDONED:
		case FINISHING_CANCEL:
		case FINISHING_ERROR:
			synchronized (this) {
				this.runnableScheduled= false;
				if (!this.graphicLocatorStarted) {
					internalStop(null);
					break;
				}
			}
			this.graphic.stopLocator(null);
			break;
		case FINISHING_OK:
			synchronized (this) {
				if (!this.graphicLocatorStarted && this.toConvert.isEmpty()) {
					internalStop(ERGraphic.LOCATOR_DONE);
					break;
				}
			}
		}
		return true;
	}
	
	@Override
	public void run(final ToolService service, final ProgressMonitor m) throws StatusException {
		double[] graphic= null;
		double[] user= null;
		while (true) {
			synchronized (this) {
				if (graphic != null) {
					if (user != null) {
						this.locatedGraphic.add(graphic);
						this.locatedUser.add(user);
					}
					else {
						// invalid point?
					}
				}
				if (this.toConvert.isEmpty()) {
					this.counter= this.locatedGraphic.size();
					this.runnableScheduled= false;
					return;
				}
				graphic= this.toConvert.remove(0);
				user= null;
			}
			user= this.graphic.convertGraphic2User(graphic, m);
		}
	}
	
	/**
	 * synchronized
	 */
	protected boolean internalScheduleConversion() {
		if (!this.runnableScheduled) {
			if (this.tool.getQueue().addHot(this).getSeverity() == Status.OK) {
				this.runnableScheduled= true;
				return true;
			}
			return false;
		}
		return true;
	}
	
	/**
	 * synchronized
	 * 
	 * @param type the stop type
	 */
	protected void internalStop(final String type) {
		assert (!this.graphicLocatorStarted);
		if (this.runnableScheduled) {
			this.tool.getQueue().removeHot(this);
			this.runnableScheduled= false;
		}
		this.started= false;
		if (type == ERGraphic.LOCATOR_DONE) {
			finished(new ArrayList<>(this.locatedGraphic), new ArrayList<>(this.locatedUser));
		}
		else {
			canceled();
		}
	}
	
	
	public boolean start() {
		synchronized (this) {
			if (this.started) {
				return false;
			}
			this.toConvert.clear();
			this.locatedGraphic.clear();
			this.locatedUser.clear();
			this.started= this.graphicLocatorStarted= true;
			this.counter= 0;
			if (this.graphic.startLocalLocator(this).getSeverity() == Status.OK) {
				return true;
			}
			else {
				this.started= this.graphicLocatorStarted= false;
				return false;
			}
		}
	}
	
	/**
	 * Is called if the locator and conversion is finished.
	 * 
	 * @param graphic the graphic coordinates
	 * @param user the user coordinates
	 */
	protected abstract void finished(final List<double[]> graphic, final List<double[]> user);
	
	/**
	 * Is called if the locator was canceled
	 */
	protected abstract void canceled();
	
}
