/*=============================================================================#
 # 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.internal.r.debug.ui.launcher;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.statushandlers.StatusManager;

import org.eclipse.statet.ecommons.preferences.core.util.PreferenceUtils;

import org.eclipse.statet.internal.r.debug.ui.RLaunchingMessages;
import org.eclipse.statet.internal.r.debug.ui.launcher.RCodeLaunchRegistry.ContentHandler.FileCommand;
import org.eclipse.statet.internal.r.ui.RUIPlugin;
import org.eclipse.statet.r.core.RCore;
import org.eclipse.statet.r.launching.ICodeSubmitContentHandler;
import org.eclipse.statet.r.launching.IRCodeSubmitConnector;
import org.eclipse.statet.r.launching.RRunDebugPreferenceConstants;
import org.eclipse.statet.r.ui.RUI;


public class RCodeLaunchRegistry {
	
	
	public static boolean isConfigured() {
		final IExtensionRegistry registry = Platform.getExtensionRegistry();
		final IConfigurationElement[] elements = registry.getConfigurationElementsFor(RUI.BUNDLE_ID, CONNECTOR_EXTENSION_POINT);
		return (elements != null && elements.length > 0);
	}
	
	
	static final String CONNECTOR_EXTENSION_POINT = "rCodeLaunchConnector"; //$NON-NLS-1$
	static final String CONTENTHANDLER_EXTENSION_POINT = "rCodeLaunchContentHandler"; //$NON-NLS-1$
	
	private static final String CONNECTOR_ELEMENT = "connector"; //$NON-NLS-1$
	private static final String CONTENTHANDLER_ELEMENT = "contentHandler"; //$NON-NLS-1$
	private static final String CONTENT_FILECOMMAND_ELEMENT = "fileCommand"; //$NON-NLS-1$
	private static final String ATT_ID = "id"; //$NON-NLS-1$
	private static final String ATT_NAME = "name"; //$NON-NLS-1$
	private static final String ATT_DESCRIPTION = "description"; //$NON-NLS-1$
	private static final String ATT_CLASS = "class"; //$NON-NLS-1$
	private static final String ATT_CONTENT_TYPE = "contentTypeId"; //$NON-NLS-1$
	private static final String ATT_HANDLER = "handler"; //$NON-NLS-1$
	private static final String ATT_DEFAULTCOMMAND = "defaultCommand"; //$NON-NLS-1$
	
	private static RCodeLaunchRegistry fgRegistry;
	
	public static synchronized RCodeLaunchRegistry getDefault() {
		if (fgRegistry == null) {
			new RCodeLaunchRegistry();
		}
		return fgRegistry;
	}
	
	
/* Config *********************************************************************/
	
	public static class ConnectorConfig {
		
		public final String fId;
		public final String fName;
		public final String fDescription;
		
		private ConnectorConfig(final IConfigurationElement element) {
			fId = element.getAttribute(ATT_ID);
			fName = element.getAttribute(ATT_NAME);
			fDescription = element.getAttribute(ATT_DESCRIPTION);
		}
	}
	
	public static class ContentHandler {
		
		public static class FileCommand {
			
			private final String fId;
			private final String fLabel;
			private final String fDefaultFileCommand;
			private String fCurrentFileCommand;
			
			
			public FileCommand(final String id, final String label, final String defaultCommand) {
				fId = id;
				fLabel = label;
				fDefaultFileCommand = fCurrentFileCommand = defaultCommand;
			}
			
			
			void setCurrentCommand(final String command) {
				fCurrentFileCommand = (command != null) ? command : fDefaultFileCommand;
			}
			
			
			public String getId() {
				return fId;
			}
			
			public String getLabel() {
				return fLabel;
			}
			
			public String getDefaultCommand() {
				return fDefaultFileCommand;
			}
			
			public String getCurrentCommand() {
				return fCurrentFileCommand;
			}
			
		}
		
		private final String fContentTypeId;
		IConfigurationElement fConfigurationElement;
		ICodeSubmitContentHandler fHandler;
		private final FileCommand[] fFileCommands;
		
		public ContentHandler(final IConfigurationElement config) {
			fContentTypeId = config.getAttribute(ATT_CONTENT_TYPE);
			fConfigurationElement = config;
			
			final IConfigurationElement[] fileCommandConfigs = config.getChildren(CONTENT_FILECOMMAND_ELEMENT);
			fFileCommands = new FileCommand[fileCommandConfigs.length];
			for (int i = 0; i < fileCommandConfigs.length; i++) {
				fFileCommands[i] = new FileCommand(
						fileCommandConfigs[i].getAttribute(ATT_ID),
						fileCommandConfigs[i].getAttribute(ATT_NAME),
						fileCommandConfigs[i].getAttribute(ATT_DEFAULTCOMMAND) );
			}
		}
		
		public String getContentTypeId() {
			return fContentTypeId;
		}
		
		public ICodeSubmitContentHandler getHandler() {
			if (fHandler == null && fConfigurationElement != null && fConfigurationElement.getAttribute(ATT_HANDLER) != null) {
				try {
					fHandler = (ICodeSubmitContentHandler) fConfigurationElement.createExecutableExtension(ATT_HANDLER);
				}
				catch (final CoreException e) {
					RUIPlugin.logError(0, "Error occurred when loading content handler", e); //$NON-NLS-1$
				}
			}
			return fHandler;
		}
		
		public FileCommand getContentFileCommand() {
			if (fFileCommands.length > 0) {
				return fFileCommands[0];
			}
			return null;
		}
		
		public FileCommand[] getFileCommands() {
			return fFileCommands;
		}
		
		public FileCommand getFileCommand(final String id) {
			for (int i = 0; i < fFileCommands.length; i++) {
				if (fFileCommands[i].fId.equals(id)) {
					return fFileCommands[i];
				}
			}
			return null;
		}
	}
	
	public static ConnectorConfig[] getAvailableConnectors() {
		final IExtensionRegistry registry = Platform.getExtensionRegistry();
		final IConfigurationElement[] elements = registry.getConfigurationElementsFor(RUI.BUNDLE_ID, CONNECTOR_EXTENSION_POINT);
		final ConnectorConfig[] configs = new ConnectorConfig[elements.length];
		for (int i = 0; i < elements.length; i++) {
			configs[i] = new ConnectorConfig(elements[i]);
		}
		return configs;
	}
	
	public static FileCommand[] getAvailableFileCommands() {
		return getDefault().getFileCommands();
	}
	
	
/* Instance *******************************************************************/
	
	private IRCodeSubmitConnector fConnector;
	private final HashMap<String, ContentHandler> fContentHandler= new HashMap<>();
	private ContentHandler fDefaultHandler;
	
	
	private RCodeLaunchRegistry() {
		fgRegistry = this;
		loadConnectorExtensions();
		loadHandlerExtensions();
		
		final IScopeContext scope= InstanceScope.INSTANCE;
		scope.getNode(RRunDebugPreferenceConstants.PREF_R_CONNECTOR.getQualifier())
				.addPreferenceChangeListener(new IPreferenceChangeListener() {
			@Override
			public void preferenceChange(final PreferenceChangeEvent event) {
				loadConnectorExtensions();
			}
		});
		scope.getNode(RRunDebugPreferenceConstants.CAT_CODELAUNCH_CONTENTHANDLER_QUALIFIER)
				.addPreferenceChangeListener(new IPreferenceChangeListener() {
			@Override
			public void preferenceChange(final PreferenceChangeEvent event) {
				loadHandlerPreferences();
			}
		});
	}
	
	
	private void loadConnectorExtensions() {
		fConnector = null;
		final IExtensionRegistry registry = Platform.getExtensionRegistry();
		final IConfigurationElement[] elements = registry.getConfigurationElementsFor(RUI.BUNDLE_ID, CONNECTOR_EXTENSION_POINT);
		
		final String id = PreferenceUtils.getInstancePrefs().getPreferenceValue(
				RRunDebugPreferenceConstants.PREF_R_CONNECTOR );
		
		for (int i = 0; i < elements.length; i++) {
			if (id.equals(elements[i].getAttribute(ATT_ID))) {
				try {
					fConnector = (IRCodeSubmitConnector) elements[i].createExecutableExtension(ATT_CLASS);
					return;
				}
				catch (final Exception e) {
					StatusManager.getManager().handle(new Status(IStatus.ERROR, RUI.BUNDLE_ID, 0,
							NLS.bind("Error loading R Launch Connector ''{0}''.", elements[i].getAttribute(ATT_NAME)), //$NON-NLS-1$
							e ));
				}
			}
		}
	}
	
	private void loadHandlerExtensions() {
		final IExtensionRegistry registry = Platform.getExtensionRegistry();
		final IConfigurationElement[] elements = registry.getConfigurationElementsFor(RUI.BUNDLE_ID, CONTENTHANDLER_EXTENSION_POINT);
		
		synchronized (fContentHandler) {
			for (int i = 0; i < elements.length; i++) {
				if (elements[i].getName().equals(CONTENTHANDLER_ELEMENT)) {
					final ContentHandler handlerData = new ContentHandler(elements[i]);
					final String contentTypeId = handlerData.getContentTypeId();
					if (contentTypeId != null && contentTypeId.length() > 0) {
						fContentHandler.put(contentTypeId, handlerData);
					}
				}
			}
			fDefaultHandler = fContentHandler.get(RCore.R_CONTENT_ID);
			if (fDefaultHandler == null) {
				throw new IllegalStateException();
			}
		}
		
		loadHandlerPreferences();
	}
	
	private void loadHandlerPreferences() {
		final IEclipsePreferences node= InstanceScope.INSTANCE.getNode(
				RRunDebugPreferenceConstants.CAT_CODELAUNCH_CONTENTHANDLER_QUALIFIER );
		if (node == null) {
			return;
		}
		synchronized (fContentHandler) {
			for (final ContentHandler data : fContentHandler.values()) {
				for (final FileCommand fileCommand : data.getFileCommands()) {
					fileCommand.setCurrentCommand(node.get(fileCommand.fId+":command", null)); //$NON-NLS-1$
				}
			}
		}
	}
	
	public IRCodeSubmitConnector getConnector() throws CoreException {
		if (fConnector == null) {
			throw new CoreException(new Status(IStatus.ERROR, RUI.BUNDLE_ID, IStatus.OK, RLaunchingMessages.SubmitCode_error_NoConnector_message, null));
		}
		
		return fConnector;
	}
	
	public ICodeSubmitContentHandler getContentHandler(final String contentType) {
		final ContentHandler data;
		synchronized (fContentHandler) {
			data = fContentHandler.get(contentType);
		}
		final ICodeSubmitContentHandler handler = (data != null) ? data.getHandler() : null;
		if (handler != null) {
			return handler;
		}
		return fDefaultHandler.getHandler();
	}
	
	public FileCommand getContentFileCommand(final String contentType) {
		final ContentHandler data;
		synchronized (fContentHandler) {
			data = fContentHandler.get(contentType);
		}
		final FileCommand fileCommand = (data != null) ? data.getContentFileCommand() : null;
		if (fileCommand != null) {
			return fileCommand;
		}
		return fDefaultHandler.getContentFileCommand();
	}
	
	public FileCommand[] getFileCommands() {
		synchronized (fContentHandler) {
			final List<FileCommand> list= new ArrayList<>(fContentHandler.size()*2);
			for (final ContentHandler data : fContentHandler.values()) {
				for (final FileCommand fileCommand : data.getFileCommands()) {
					list.add(fileCommand);
				}
			}
			return list.toArray(new FileCommand[list.size()]);
		}
	}
	
	public FileCommand getFileCommand(final String id) {
		synchronized (fContentHandler) {
			for (final ContentHandler data : fContentHandler.values()) {
				for (final FileCommand fileCommand : data.getFileCommands()) {
					if (fileCommand.getId().equals(id)) {
						return fileCommand;
					}
				}
			}
		}
		return null;
	}
	
}
