/**
 * @author    STF 424_ITS_Test_Platform
 * @version    $id$
 */
package org.etsi.ttcn.tool.spirent.xf;

import java.util.Arrays;

import org.etsi.ttcn.extfunc.core.ExternalFunction;
import org.etsi.ttcn.extfunc.core.XfFactory;

import com.testingtech.ttcn.extension.ExternalFunctionsProvider;
import com.testingtech.ttcn.tri.ExternalFunctionsDefinition;

import de.tu_berlin.cs.uebb.muttcn.runtime.RB;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodCall;

/**
 * This class provides access to the implementation of TTCN-3 external function
 */
public class ExternalFunctionsPluginProvider implements ExternalFunctionsProvider {

	private ExternalFunction xf = null;
	
    /** 
     * Constructor
     * 
     */
    public ExternalFunctionsPluginProvider() {
    	xf = XfFactory.getInstance().getXf("");
    }

    /** 
     * Refer to TTwb developer's guide
     */
    @Override
    public ExternalFunctionsDefinition getExternalFunctions(RB rb) {    	

    	Class<?> dynamicType;
		try {
			dynamicType = new ByteBuddy()    	
					  .subclass(xf.getClass())
					  .defineConstructor(Arrays.<Class<?>>asList(RB.class), Visibility.PUBLIC)
					  .intercept(MethodCall.invoke(xf.getClass().getDeclaredConstructor()))
					  .implement(ExternalFunctionsDefinition.class)
					  .name("XfPlugin")
					  .make()
					  .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
					  .getLoaded();
				    	
			return (ExternalFunctionsDefinition) dynamicType.newInstance();
		} catch (InstantiationException | IllegalAccessException | SecurityException | NoSuchMethodException e) {
			e.printStackTrace();
			return null;
		}
    }

}
