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

package org.eclipse.statet.r.console.core;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.ToolRunnable;
import org.eclipse.statet.jcommons.ts.core.ToolService;

import org.eclipse.statet.ltk.model.core.element.SourceUnit;
import org.eclipse.statet.nico.core.runtime.ITrack;
import org.eclipse.statet.nico.core.runtime.Queue.Section;
import org.eclipse.statet.nico.core.runtime.SubmitType;
import org.eclipse.statet.nico.core.runtime.ToolController;
import org.eclipse.statet.nico.core.runtime.ToolStreamProxy;
import org.eclipse.statet.nico.core.util.TrackWriter;
import org.eclipse.statet.nico.core.util.TrackingConfiguration;
import org.eclipse.statet.r.console.core.RWorkspace.Changes;
import org.eclipse.statet.r.nico.IRSrcref;


/**
 * Abstract superclass of controllers for R.
 * 
 * All implementations of {@link ToolController} for R should extends this class.
 */
public abstract class AbstractRController extends ToolController
		implements IRBasicAdapter {
	
	
	public static class RCommandRunnable extends ConsoleCommandRunnable {
		
		protected RCommandRunnable(final String text, final SubmitType type) {
			super(text, type);
		}
		
		@Override
		public boolean canRunIn(final Tool tool) {
			return (tool.isProvidingFeatureSet(RConsoleTool.R_BASIC_FEATURESET_ID));
		}
		
		@Override
		public void run(final ToolService service,
				final ProgressMonitor m) throws StatusException {
			final IRBasicAdapter r = (IRBasicAdapter) service;
			r.briefAboutToChange();
			try {
				super.run(r, m);
			}
			finally {
				if ((r.getPrompt().meta & IRBasicAdapter.META_PROMPT_INCOMPLETE_INPUT) == 0) {
					r.briefChanged(RWorkspace.REFRESH_AUTO);
				}
			}
		}
		
	}
	
	
	public static final String INIT_RGRAPHIC_FACTORY_HANDLER_ID = "r/initRGraphicFactory"; //$NON-NLS-1$
	
	protected final List<ToolRunnable> startupsRunnables= new ArrayList<>();
	
	protected String continuePromptText;
	protected String defaultPromptText;
	
	private List<TrackingConfiguration> trackingConfigurations;
	
	
	public AbstractRController(final RProcess process,
			final Map<String, Object> connectionInfo) {
		super(process, connectionInfo);
		process.registerFeatureSet(RConsoleTool.R_BASIC_FEATURESET_ID);
	}
	
	
	public void addStartupRunnable(final ToolRunnable runnable) {
		this.startupsRunnables.add(runnable);
	}
	
	@Override
	public RProcess getTool() {
		return (RProcess) super.getTool();
	}
	
	@Override
	public RWorkspace getWorkspaceData() {
		return (RWorkspace) super.getWorkspaceData();
	}
	
	@Override
	protected SystemRunnable createCancelPostRunnable(final int options) {
		return new ControllerSystemRunnable(
				"common/cancel/post", "Reset prompt") { //$NON-NLS-1$
			
			@Override
			public void run(final ToolService s,
					final ProgressMonitor m) throws StatusException {
				if (!isTerminated()) {
					postCancelTask(options, m);
				}
			}
			
		};
	}
	
	protected void postCancelTask(final int options,
			final ProgressMonitor m) throws StatusException {
		final ToolStreamProxy streams = getStreams();
		final SubmitType submitType = getCurrentSubmitType();
		final String text = this.fCurrentPrompt.text + (
				((this.fCurrentPrompt.meta & IRBasicAdapter.META_PROMPT_INCOMPLETE_INPUT) != 0) ?
						"(Input cancelled)" : "(Command cancelled)") + 
						this.fLineSeparator;
		streams.getInfoStreamMonitor().append(text, submitType, this.fCurrentPrompt.meta);
	}
	
	public boolean supportsBusy() {
		return false;
	}
	
	public boolean isBusy() {
		return false;
	}
	
	
//-- Runnable Adapter
	@Override
	protected void initRunnableAdapterL() {
		super.initRunnableAdapterL();
		setDefaultPromptTextL("> "); //$NON-NLS-1$
		setContinuePromptText("+ "); //$NON-NLS-1$
	}
	
	protected void setTracksConfig(final List<TrackingConfiguration> config) {
		this.trackingConfigurations= config;
	}
	
	protected void initTracks(final String directory,
			final ProgressMonitor m, final List<Status> warnings) throws StatusException {
		if (this.trackingConfigurations != null) {
			m.setWorkRemaining(this.trackingConfigurations.size());
			final List<ITrack> tracks= new ArrayList<>(this.trackingConfigurations.size());
			for (final TrackingConfiguration trackingConfig : this.trackingConfigurations) {
				final TrackWriter tracker= new TrackWriter(this, trackingConfig);
				final Status status= tracker.init(m.newSubMonitor(1));
				if (status.getSeverity() == Status.OK) {
					tracks.add(tracker);
					addDisposable(tracker);
				}
				else {
					warnings.add(status);
				}
			}
			setTracks(tracks);
		}
	}
	
	
	@Override
	public ToolRunnable createCommandRunnable(final String command, final SubmitType type) {
		return new RCommandRunnable(command, type);
	}
	
	@Override
	public void setDefaultPromptTextL(String text) {
		if (text == null || text.equals(this.defaultPromptText)) {
			return;
		}
		text = text.intern();
		this.defaultPromptText = text;
		super.setDefaultPromptTextL(text);
	}
	
	public void setContinuePromptText(String text) {
		if (text == null || text.equals(this.continuePromptText)) {
			return;
		}
		text = text.intern();
		this.continuePromptText = text;
	}
	
	
	@Override
	protected void doRunSuspendedLoopL(final int o, final int level, final Section queueSection) {
		briefChanged(RWorkspace.REFRESH_AUTO);
		final Changes savedChanges= getWorkspaceData().saveChanges();
		try {
			super.doRunSuspendedLoopL(o, level, queueSection);
		}
		finally {
			getWorkspaceData().restoreChanges(savedChanges);
		}
	}
	
	public Set<Long> getLazyEnvironments(final ProgressMonitor m) {
		return null;
	}
	
	public void submitFileCommandToConsole(final String[] lines, final SourceUnit file,
			final ProgressMonitor m) throws StatusException {
		for (final String line : lines) {
			submitToConsole(line, m);
		}
	}
	
	public void submitCommandToConsole(final String[] lines, final IRSrcref srcref,
			final ProgressMonitor m) throws StatusException {
		for (final String line : lines) {
			submitToConsole(line, m);
		}
	}
	
	
	@Override
	protected void doQuitL(final ProgressMonitor m) throws StatusException {
		submitToConsole("q()", m); //$NON-NLS-1$
	}
	
	@Override
	public void quit(final ProgressMonitor m) throws StatusException {
		doQuitL(m);
	}
	
}
