package com.google.ajiel.domain.payroll;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.codehaus.groovy.control.CompilationFailedException;
import org.codehaus.groovy.runtime.InvokerHelper;

import com.google.ajiel.service.ajielutil.AjielGroovyUtil;
import com.google.ajiel.service.cache.UtilCache;
import com.google.ajiel.service.util.GeneralException;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;

import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyShell;

@Entity
public class GrooyScript{
    private static final String ENCODE = "UTF-8";
    private static final String LINE_SEPARATOR = System.getProperty("line.separator");

	
	@Id long id;
	String name;
	int seq;
	String groovyScript;

    public static UtilCache<String, Class<?>> parsedScripts = UtilCache.createUtilCache("script.WagetypeGroovyParsedCache",0,0);
    public static GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
	
	public GrooyScript(String name, String groovyScript, int seq) {
		 this.name = name;
		 this.seq = seq;
		 this.groovyScript = groovyScript;
		 /*
		 UtilCache.createUtilCache("script.WagetypeGroovyParsedCache",0,0);
		 parsedScripts = UtilCache.findCache("script.WagetypeGroovyParsedCache");
		 */
	}

	public String getName() {
		return this.name;
	}
	public String getGroovyScript() {
		return this.groovyScript;
	}

	public Key<GrooyScript> getKey() {
    	return Key.create(GrooyScript.class,this.id);
    }

	public Object runScript (Map<String, Object> context) throws GeneralException {
		return runScript(getKey().toString(), getGroovyScript(), context);
	}

/*
 * STATICS	
 */
	public static Object runScript (String keyStr, String groovyScript, Map<String, Object> context) throws GeneralException {
		try {
    		Class<?> scriptClass;
            scriptClass = parsedScripts.get(keyStr);
            if (scriptClass == null) {
                scriptClass = groovyClassLoader.parseClass(groovyScript);
                parsedScripts.put(keyStr, scriptClass);
            }
            Binding binding = new Binding();
            binding.setVariable("context", context);
            return InvokerHelper.createScript(scriptClass,binding).run();
        } catch (CompilationFailedException e) {
            String errMsg = "Error loading Groovy script [" + keyStr + "]: " + e.toString();
            throw new GeneralException(errMsg, e);
        }		
	}
	
	
/*
	public static List<PayResult> runScriptList (List<Script> scriptList) {
		
		for (Script script : scriptList) {
			List<PayResult> payResultList = Script.runScript(script);
			
		}
		List<PayResult> payResultList = new ArrayList<>(0);
		return payResultList;
		
	}
	*/
/*	
	public static List<GenericValue> runPayrollSimulation(Map<String,Object> context, List<GenericValue> scripts, ModelEntity resultModel, String delegatorName ) {
		for (GenericValue script : scripts){
			String scriptId = script.getString("scriptId");
			try{
				Object result = GroovyUtil.runScript(script.getString("schemaId"),script.getString("scriptId"),script.getString("script"), context,delegatorName);
				context.put(scriptId, result);
				Debug.logInfo("scriptId: " + scriptId, module);
				Debug.logInfo("result: " + result, module);
			}catch(Exception e){
				Debug.logInfo("scriptId: " + scriptId, module);
				e.printStackTrace();
				return null;
			}
		}
		Debug.logInfo("context: " + context, module);
		List<GenericValue> payResult = FastList.newInstance();
		for (GenericValue script : scripts){
			Object obj = context.get(script.getString("scriptId"));
			if(obj instanceof List){
				List<Map<String,Object>> results = (List<Map<String,Object>>) obj;
				for(Map<String,Object> result : results){
					payResult.add(getPayResult(result, script,resultModel));
				}
			}else if(obj instanceof Map){
				payResult.add(getPayResult((Map<String,Object>) obj, script,resultModel));
			}
		}
		return payResult;
	}
	*/

}
