package org.eclipse.scanning.points;

import java.util.Iterator;
import java.util.Properties;

import org.python.core.Py;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PySystemState;

/**
 * Based on JythonObjectFactory
 * See: http://www.jython.org/jythonbook/en/1.0/JythonAndJavaIntegration.html#more-efficient-version-of-loosely-coupled-object-factory
 */
public class ScanPointGeneratorFactory {
	// This class compiles Jython objects and maps them to an IPointGenerator so they can be
	// used easily in Java. More specifically, it creates the Jython ScanPointGenerator interface
	// classes found in the scripts folder of this package (org.eclipse.scanning.points)
	
	// These are the constructors for each Jython SPG interface. To add a new one just replace, 
	// for example, "JArrayGenerator" with your new class and give the constructor a new name
	// like "<YourClass>Factory"
    public static JythonObjectFactory JLineGenerator1DFactory() {
        return new JythonObjectFactory(Iterator.class, "jython_spg_interface", "JLineGenerator1D");
    }
	
    public static JythonObjectFactory JLineGenerator2DFactory() {
        return new JythonObjectFactory(Iterator.class, "jython_spg_interface", "JLineGenerator2D");
    }
	
    public static JythonObjectFactory JArrayGeneratorFactory() {
        return new JythonObjectFactory(Iterator.class, "jython_spg_interface", "JArrayGenerator");
    }
	
    public static JythonObjectFactory JRasterGeneratorFactory() {
        return new JythonObjectFactory(Iterator.class, "jython_spg_interface", "JRasterGenerator");
    }
	
    public static JythonObjectFactory JSpiralGeneratorFactory() {
        return new JythonObjectFactory(Iterator.class, "jython_spg_interface", "JSpiralGenerator");
    }
	
    public static JythonObjectFactory JLissajousGeneratorFactory() {
        return new JythonObjectFactory(Iterator.class, "jython_spg_interface", "JLissajousGenerator");
    }
	
    public static JythonObjectFactory JCompoundGeneratorFactory() {
        return new JythonObjectFactory(Iterator.class, "jython_spg_interface", "JCompoundGenerator");
    }
	
    public static JythonObjectFactory JRandomOffsetMutatorFactory() {
        return new JythonObjectFactory(PyObject.class, "jython_spg_interface", "JRandomOffsetMutator");
    }
    
    // This class creates Java objects from Jython classes
    public static class JythonObjectFactory {
        private final Class javaClass;
        private final PyObject pyClass;
        
        // Constructor obtains a reference to the importer, module, and the class name
        public JythonObjectFactory(PySystemState state, Class javaClass, String moduleName, String className) {Properties postProperties = new Properties();
        	
            state.path.add(new PyString("/scratch/workspaces/workspace_git/daq-eclipse.git/org.eclipse.scanning.points/scripts/"));
            
            this.javaClass = javaClass;
            PyObject importer = state.getBuiltins().__getitem__(Py.newString("__import__"));
            PyObject module = importer.__call__(Py.newString(moduleName));
            pyClass = module.__getattr__(className);
            // System.err.println("module=" + module + ",class=" + klass);
        }
        
        // This constructor passes through to the other constructor with the SystemState
        public JythonObjectFactory(Class javaClass, String moduleName, String className) {
            this(Py.getSystemState(), javaClass, moduleName, className);
        }
        
        // The following methods return a coerced Jython object based upon the pieces of
        // information that were passed into the factory, for various argument structures
        
        public Object createObject() {
            return pyClass.__call__().__tojava__(javaClass);
        }
        public Object createObject(Object arg1) {
            return pyClass.__call__(Py.java2py(arg1)).__tojava__(javaClass);
        }
        public Object createObject(Object arg1, Object arg2) {
            return pyClass.__call__(Py.java2py(arg1), Py.java2py(arg2)).__tojava__(javaClass);
        }
        public Object createObject(Object arg1, Object arg2, Object arg3) {
            return pyClass.__call__(Py.java2py(arg1), Py.java2py(arg2), Py.java2py(arg3)).__tojava__(javaClass);
        }
        public Object createObject(Object args[], String keywords[]) {
            PyObject convertedArgs[] = new PyObject[args.length];
            for (int i = 0; i < args.length; i++) {
                convertedArgs[i] = Py.java2py(args[i]);
            }
            return pyClass.__call__(convertedArgs, keywords).__tojava__(javaClass);
        }
        public Object createObject(Object... args) {
            return createObject(args, Py.NoKeywords);
        }
    }
}
@@ -47,52 +47,222 @@
 ava.
-util.Iterator;%0Aimport java.util.Properties;%0A
+io.File;%0Aimport java.io.IOException;%0Aimport java.util.Iterator;%0Aimport java.util.Properties;%0A%0Aimport org.eclipse.core.runtime.FileLocator;%0Aimport org.eclipse.core.runtime.Platform;%0Aimport org.osgi.framework.Bundle;
 %0Aimp
@@ -2896,16 +2896,36 @@
 sName) %7B
+%0A        %09%0A        %09
 Properti
@@ -2988,114 +2988,134 @@
     
-state.path.add(new PyString(%22/scratch/workspaces/workspace_git/daq-eclipse.git/org.eclipse.scanning.points
+File loc = getBundleLocation(%22org.eclipse.scanning.points%22);%0A            state.path.add(new PyString(loc.getAbsolutePath() + %22
 /scr
@@ -5042,9 +5042,557 @@
 %7D%0A    %7D%0A
+    %0A    %0A    /**%0A%09 * @param bundleName%0A%09 * @return file this can return null if bundle is not found%0A%09 */%0A%09public static File getBundleLocation(final String bundleName) %7B%0A%09%09final Bundle bundle = Platform.getBundle(bundleName);%0A%09%09if (bundle == null) %7B%0A%09%09%09return new File(%22/scratch/workspaces/workspace_git/daq-eclipse.git/org.eclipse.scanning.points%22);%0A%09%09%7D%0A%09%09try %7B%0A%09%09%09return FileLocator.getBundleFile(bundle);%0A%09%09%7D%0A%09%09catch (IOException e) %7B%0A%09%09%09return new File(%22/scratch/workspaces/workspace_git/daq-eclipse.git/org.eclipse.scanning.points%22);%0A%09%09%7D%0A%09%7D%0A%0A
 %7D

Refactor to get bundle location to add scripts folder to path