package org.eclipse.ptp.rm.jaxb.core.rm;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.ptp.core.IPTPLaunchConfigurationConstants;
import org.eclipse.ptp.core.elements.IPUniverse;
import org.eclipse.ptp.remote.core.IRemoteConnection;
import org.eclipse.ptp.remote.core.IRemoteConnectionManager;
import org.eclipse.ptp.remote.core.IRemoteFileManager;
import org.eclipse.ptp.remote.core.IRemoteServices;
import org.eclipse.ptp.remote.core.PTPRemoteCorePlugin;
import org.eclipse.ptp.remote.core.exception.RemoteConnectionException;
import org.eclipse.ptp.rm.jaxb.core.IJAXBNonNLSConstants;
import org.eclipse.ptp.rm.jaxb.core.data.Command;
import org.eclipse.ptp.rm.jaxb.core.data.Control;
import org.eclipse.ptp.rm.jaxb.core.data.Control.SubmitCommands;
import org.eclipse.ptp.rm.jaxb.core.data.DiscoverAttributes;
import org.eclipse.ptp.rm.jaxb.core.data.HoldJob;
import org.eclipse.ptp.rm.jaxb.core.data.JobAttribute;
import org.eclipse.ptp.rm.jaxb.core.data.ManagedFiles;
import org.eclipse.ptp.rm.jaxb.core.data.OnShutDown;
import org.eclipse.ptp.rm.jaxb.core.data.OnStartUp;
import org.eclipse.ptp.rm.jaxb.core.data.Property;
import org.eclipse.ptp.rm.jaxb.core.data.ReleaseJob;
import org.eclipse.ptp.rm.jaxb.core.data.ResumeJob;
import org.eclipse.ptp.rm.jaxb.core.data.Script;
import org.eclipse.ptp.rm.jaxb.core.data.SubmitBatch;
import org.eclipse.ptp.rm.jaxb.core.data.SubmitDebug;
import org.eclipse.ptp.rm.jaxb.core.data.SubmitInteractive;
import org.eclipse.ptp.rm.jaxb.core.data.SuspendJob;
import org.eclipse.ptp.rm.jaxb.core.data.TerminateJob;
import org.eclipse.ptp.rm.jaxb.core.messages.Messages;
import org.eclipse.ptp.rm.jaxb.core.runnable.CommandJob;
import org.eclipse.ptp.rm.jaxb.core.runnable.ManagedFilesJob;
import org.eclipse.ptp.rm.jaxb.core.runnable.ScriptHandler;
import org.eclipse.ptp.rm.jaxb.core.utils.CoreExceptionUtils;
import org.eclipse.ptp.rm.jaxb.core.variables.RMVariableMap;
import org.eclipse.ptp.rmsystem.AbstractResourceManager;
import org.eclipse.ptp.rmsystem.IJobStatus;
import org.eclipse.ptp.rmsystem.IResourceManagerConfiguration;

public final class JAXBResourceManager extends AbstractResourceManager implements IJAXBNonNLSConstants {

	private final IJAXBResourceManagerConfiguration config;
	private final Control controlData;

	private IRemoteServices remoteServices;
	private IRemoteServices localServices;
	private IRemoteConnectionManager remoteConnectionManager;
	private IRemoteConnectionManager localConnectionManager;
	private IRemoteConnection remoteConnection;
	private IRemoteConnection localConnection;
	private IRemoteFileManager remoteFileManager;
	private IRemoteFileManager localFileManager;

	private final Map<String, String> dynSystemEnv;
	private boolean appendSysEnv;

	public JAXBResourceManager(IPUniverse universe, IResourceManagerConfiguration jaxbServiceProvider) {
		super(universe, jaxbServiceProvider);
		config = (IJAXBResourceManagerConfiguration) jaxbServiceProvider;
		controlData = config.resourceManagerData().getControl();
		dynSystemEnv = new HashMap<String, String>();
	}

	public boolean getAppendSysEnv() {
		return appendSysEnv;
	}

	public IJAXBResourceManagerConfiguration getConfig() {
		return config;
	}

	public Map<String, String> getDynSystemEnv() {
		return dynSystemEnv;
	}

	public IRemoteConnection getLocalConnection() {
		return localConnection;
	}

	public IRemoteConnectionManager getLocalConnectionManager() {
		return localConnectionManager;
	}

	public IRemoteFileManager getLocalFileManager() {
		return localFileManager;
	}

	public IRemoteConnection getRemoteConnection() {
		return remoteConnection;
	}

	public IRemoteConnectionManager getRemoteConnectionManager() {
		return remoteConnectionManager;
	}

	public IRemoteFileManager getRemoteFileManager() {
		return remoteFileManager;
	}

	public IRemoteServices getRemoteServices() {
		return remoteServices;
	}

	@Override
	protected void doCleanUp() {
		config.clearReferences();
	}

	@Override
	protected void doControlJob(String jobId, String operation, IProgressMonitor monitor) throws CoreException {
		resetEnv();
		updateJobId(jobId);
		doControlCommand(operation);
	}

	@Override
	protected void doDispose() {
		// NOP for the moment
	}

	@Override
	protected void doShutdown() throws CoreException {
		resetEnv();
		doOnShutdown();
		doDisconnect();
	}

	@Override
	protected void doStartup(IProgressMonitor monitor) throws CoreException {
		resetEnv();
		initializeConnections();
		try {
			doConnect(monitor);
		} catch (RemoteConnectionException t) {
			throw CoreExceptionUtils.newException(t.getMessage(), t);
		}
		doOnStartUp(monitor);
		maybeDiscoverAttributes(monitor);
	}

	@Override
	protected IJobStatus doSubmitJob(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor)
			throws CoreException {
		resetEnv();
		updatePropertyValuesFromTab(configuration);
		/*
		 * create the script if necessary; adds the contents to env as
		 * "${rm:script}"
		 */
		maybeHandleScript(controlData.getScript());
		maybeHandleManagedFiles(controlData.getManagedFiles());
		doJobSubmitCommand(mode);
		/*
		 * parser will have set the jobId in the map
		 */
		return getJobStatus(currentJobId());
	}

	/*
	 * @see updateJobId
	 */
	private String currentJobId() {
		return (String) RMVariableMap.getActiveInstance().getVariables().get(JOB_ID);
	}

	/*
	 * If there are special server connections to open, those need to be taken
	 * care of by a command to be run on start-up; here we just check for open
	 * connections.
	 */
	private void doConnect(IProgressMonitor monitor) throws RemoteConnectionException {
		if (!localConnection.isOpen()) {
			localConnection.open(monitor);
		}
		if (!remoteConnection.isOpen()) {
			remoteConnection.open(monitor);
		}
	}

	/*
	 * If the command is not supported, throws exception
	 */
	private void doControlCommand(String operation) throws CoreException {
		CoreException ce = CoreExceptionUtils.newException(Messages.RMNoSuchCommandError + operation, null);
		List<String> cmds = null;
		if (TERMINATE_OPERATION.equals(operation)) {
			TerminateJob job = controlData.getTerminateJob();
			if (job == null) {
				throw ce;
			}
			cmds = job.getCommandRef();
		} else if (SUSPEND_OPERATION.equals(operation)) {
			SuspendJob job = controlData.getSuspendJob();
			if (job == null) {
				throw ce;
			}
			cmds = job.getCommandRef();
		} else if (RESUME_OPERATION.equals(operation)) {
			ResumeJob job = controlData.getResumeJob();
			if (job == null) {
				throw ce;
			}
			cmds = job.getCommandRef();
		} else if (RELEASE_OPERATION.equals(operation)) {
			ReleaseJob job = controlData.getReleaseJob();
			if (job == null) {
				throw ce;
			}
			cmds = job.getCommandRef();
		} else if (HOLD_OPERATION.equals(operation)) {
			HoldJob job = controlData.getHoldJob();
			if (job == null) {
				throw ce;
			}
			cmds = job.getCommandRef();
		}
		runCommands(cmds, operation);
	}

	/*
	 * Close the connections.
	 */
	private void doDisconnect() {
		if (localConnection.isOpen()) {
			localConnection.close();
		}
		if (!remoteConnection.isOpen()) {
			remoteConnection.close();
		}
	}

	/*
	 * Run either in interactive, batch or debug mode. right now,
	 * ILaunchManager.RUN_MODE and ILaunchManager.DEBUG_MODE are the two
	 * choices, meaning a single configuration cannot support both batch and
	 * interactive.
	 */
	private void doJobSubmitCommand(String mode) throws CoreException {
		SubmitCommands commands = controlData.getSubmitCommands();
		if (commands == null) {
			throw CoreExceptionUtils.newException(Messages.MissingRunCommandsError, null);
		}
		List<Object> list = commands.getSubmitInteractiveOrSubmitBatchOrSubmitDebug();
		List<String> cmds = null;
		// check mode for type
		for (Object job : list) {
			if (job instanceof SubmitInteractive) {
				SubmitInteractive interactive = (SubmitInteractive) job;
				if (ILaunchManager.RUN_MODE.equals(mode)) {
					cmds = interactive.getCommandRef();
					break;
				}
			} else if (job instanceof SubmitBatch) {
				SubmitBatch batch = (SubmitBatch) job;
				if (ILaunchManager.RUN_MODE.equals(mode)) {
					cmds = batch.getCommandRef();
					break;
				}
			} else if (job instanceof SubmitDebug) {
				SubmitDebug debug = (SubmitDebug) job;
				if (ILaunchManager.DEBUG_MODE.equals(mode)) {
					cmds = debug.getCommandRef();
					break;
				}
			}
		}
		runCommands(cmds, mode);
	}

	/*
	 * Run the shut down commands, if any
	 */
	private void doOnShutdown() throws CoreException {
		OnShutDown onShutDown = controlData.getOnShutDown();
		if (onShutDown == null) {
			return;
		}
		runCommands(onShutDown.getCommandRef(), SHUTDOWN);
	}

	/*
	 * Run the start up commands, if any
	 */
	private void doOnStartUp(IProgressMonitor monitor) throws CoreException {
		OnStartUp onStartUp = controlData.getOnStartUp();
		if (onStartUp == null) {
			return;
		}
		runCommands(onStartUp.getCommandRef(), STARTUP);
	}

	/*
	 * For use by the command and file jobs.
	 */
	private void initializeConnections() {
		localServices = PTPRemoteCorePlugin.getDefault().getDefaultServices();
		assert (localServices != null);
		localConnectionManager = localServices.getConnectionManager();
		assert (localConnectionManager != null);
		/*
		 * Since it's a local service, it doesn't matter which parameter is
		 * passed
		 */
		localConnection = localConnectionManager.getConnection(ZEROSTR);
		assert (localConnection != null);
		localFileManager = localServices.getFileManager(localConnection);
		assert (localFileManager != null);
		remoteServices = PTPRemoteCorePlugin.getDefault()
				.getRemoteServices(config.getRemoteServicesId(), new NullProgressMonitor());
		assert (null != remoteServices);
		remoteConnectionManager = remoteServices.getConnectionManager();
		assert (null != remoteConnectionManager);
		remoteConnection = remoteConnectionManager.getConnection(config.getConnectionName());
		assert (null != remoteConnection);
		remoteFileManager = remoteServices.getFileManager(remoteConnection);
		assert (null != remoteFileManager);
	}

	private void maybeAddProperty(String name, String value, Map<String, Object> env) {
		if (value == null) {
			return;
		}
		Property p = new Property();
		p.setName(name);
		p.setValue(value);
		env.put(name, p);
	}

	/*
	 * Run the discover attributes commands, if any; these can include queues,
	 * for instance.
	 */
	private void maybeDiscoverAttributes(IProgressMonitor monitor) throws CoreException {
		DiscoverAttributes discoverAttributes = controlData.getDiscoverAttributes();
		if (discoverAttributes == null) {
			return;
		}
		runCommands(discoverAttributes.getCommandRef(), DISCATTR);
	}

	/*
	 * Write necessary content and stage to host if necessary.
	 */
	private void maybeHandleManagedFiles(ManagedFiles files) throws CoreException {
		ManagedFilesJob job = new ManagedFilesJob(files, localFileManager, remoteFileManager);
		job.schedule();
		try {
			job.join();
		} catch (InterruptedException t) {
			t.printStackTrace();
		}
	}

	/*
	 * Serialize script content if necessary.
	 */
	private void maybeHandleScript(Script script) {
		if (script == null) {
			return;
		}
		ScriptHandler job = new ScriptHandler(script, dynSystemEnv, appendSysEnv);
		job.schedule();
		try {
			job.join();
		} catch (InterruptedException t) {
			t.printStackTrace();
		}
	}

	private void maybeOverwrite(String key1, String key2, ILaunchConfiguration configuration, Map<String, Object> env)
			throws CoreException {
		String value = null;
		Property p = (Property) env.get(key1);
		if (p != null) {
			value = p.getValue();
		}
		value = configuration.getAttribute(key2, value);
		maybeAddProperty(key1, value, env);
	}

	private void resetEnv() {
		config.setActive();
		setFixedConfigurationProperties();
		dynSystemEnv.clear();
		appendSysEnv = true;
	}

	/*
	 * Create command job, schedule and join.
	 */
	private void runCommand(String commandRef) throws CoreException {
		Command command = (Command) RMVariableMap.getActiveInstance().getVariables().get(commandRef);
		if (command == null) {
			throw CoreExceptionUtils.newException(Messages.RMNoSuchCommandError + commandRef, null);
		}
		CommandJob job = new CommandJob(command, this);
		job.schedule();
		try {
			job.join();
		} catch (InterruptedException t) {
			t.printStackTrace();
		}
	}

	/*
	 * Run command sequence.
	 */
	private void runCommands(List<String> cmds, String operation) throws CoreException {
		if (cmds == null) {
			throw CoreExceptionUtils.newException(Messages.EmptyCommandDef + operation, null);
		}
		for (String ref : cmds) {
			runCommand(ref);
		}
	}

	/*
	 * From the user runtime choices.
	 */
	private void setFixedConfigurationProperties() {
		Map<String, Object> env = RMVariableMap.getActiveInstance().getVariables();
		env.put(CONTROL_USER_VAR, config.getControlUserName());
		env.put(MONITOR_USER_VAR, config.getMonitorUserName());
		env.put(CONTROL_ADDRESS_VAR, config.getControlAddress());
		env.put(MONITOR_ADDRESS_VAR, config.getMonitorAddress());
	}

	/*
	 * @warning: current implementation treats jobs serially; only one jobId can
	 * be in the map at a time.
	 */
	private void updateJobId(String jobId) {
		RMVariableMap.getActiveInstance().getVariables().put(JOB_ID, jobId);
	}

	/*
	 * Transfers the values from the configuration to the live map.
	 */
	@SuppressWarnings("unchecked")
	private void updatePropertyValuesFromTab(ILaunchConfiguration configuration) throws CoreException {
		Map<String, String> lcattr = configuration.getAttributes();
		Map<String, Object> env = RMVariableMap.getActiveInstance().getVariables();
		for (String key : lcattr.keySet()) {
			String value = lcattr.get(key);
			Object target = env.get(key);
			if (target instanceof Property) {
				((Property) target).setValue(value);
			} else if (target instanceof JobAttribute) {
				((JobAttribute) target).setValue(value);
			}
		}

		dynSystemEnv.putAll(configuration.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, dynSystemEnv));
		appendSysEnv = configuration.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, appendSysEnv);
		maybeOverwrite(DIRECTORY, IPTPLaunchConfigurationConstants.ATTR_WORKING_DIR, configuration, env);
		maybeOverwrite(EXEC_PATH, IPTPLaunchConfigurationConstants.ATTR_EXECUTABLE_PATH, configuration, env);
		maybeOverwrite(PROG_ARGS, IPTPLaunchConfigurationConstants.ATTR_ARGUMENTS, configuration, env);
	}
}
