/*******************************************************************************
 * Copyright (c) 2012 Joseph Carroll
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Joseph Carroll <jdsalingerjr@gmail.com> - initial API and implementation
 *******************************************************************************/
package braintrader.platform.workbench.common;

import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExecutableExtension;
import org.eclipse.core.runtime.IExecutableExtensionFactory;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.InjectionException;
import org.eclipse.emf.common.util.URI;
import org.osgi.framework.Bundle;

import braintrader.core.di.InjectorConstants;
import braintrader.platform.workbench.util.URIAssistant;

/**
 * @author Joseph Carroll
 *
 */
public abstract class InjectableExecutableExtensionFactory implements IExecutableExtension, IExecutableExtensionFactory {

	URI resourceURI;
	IEclipseContext workbenchContext;
	IEclipseContext traderContext;
	
	IConfigurationElement config;

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
	 */
	@Override
	abstract public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException;
	
	protected void parseInitializationData(IConfigurationElement config, Map<String,Object> parameterMap) throws CoreException {
		this.config = config;
		String resourceKey = (String) parameterMap.get(InjectorConstants.CONTRIBUTION_URI);
		workbenchContext = (IEclipseContext) parameterMap.get(InjectorConstants.WORKBENCH_CONTEXT);
		traderContext = (IEclipseContext) parameterMap.get(InjectorConstants.TRADER_CONTEXT);
		// Allow for any other mapped parameters...
				
		if (resourceKey != null) {
			if (resourceKey.startsWith("platform:/plugin/")) { //$NON-NLS-1$
				// log?? "platform-style URIs deprecated for referencing types: use bundleclass://<bundlename>/<typename>"); //$NON-NLS-1$
				resourceKey.replace("platform:/plugin/", "bundleclass://"); //$NON-NLS-1$ //$NON-NLS-2$
			} 
			resourceURI = URI.createURI(resourceKey);
		}

		if (resourceURI == null) {
			throw new CoreException(new Status(IStatus.ERROR, resourceKey, "Invalid resource URI: ",
					new IllegalArgumentException("Invalid resource key : " + resourceKey)));
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IExecutableExtensionFactory#create()
	 */
	@Override
	public Object create() throws CoreException {
		Object result = null;
		try {
			Bundle bundle = URIAssistant.getBundle(resourceURI);
			String clazz = resourceURI.segment(0);
			Class<?> targetClass = bundle.loadClass(clazz);
			// Eclipse Injected Result!!
			result = ContextInjectionFactory.make(targetClass, workbenchContext, traderContext);
		} catch (InjectionException | ClassNotFoundException e) {
			throw new CoreException(new Status(IStatus.ERROR, resourceURI.toString(), "Unable to create: ", e));
		}	
		if (result instanceof IExecutableExtension) {
			((IExecutableExtension) result).setInitializationData(config, null, null);
		}
		return result;
	}

}
