package org.spbu.benchmark.app;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

import org.spbu.benchmark.Action;
import org.spbu.benchmark.ActionResult;
import org.spbu.benchmark.BenchmarkException;
import org.spbu.benchmark.LoggingSupport;

import com.progress.open4gl.javaproxy.OpenAppObject;
import com.progress.open4gl.javaproxy.OpenProcObject;
import com.progress.open4gl.javaproxy.ParamArray;
/**
 * <p>Java class for PersistentAppAction complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="PersistentAppAction">
 *   &lt;complexContent>
 *     &lt;extension base="{}AppAction">
 *       &lt;sequence>
 *         &lt;element name="functions" type="{}ProcInvocation" maxOccurs="unbounded" minOccurs="0"/>
 *       &lt;/sequence>
 *     &lt;/extension>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.NONE)
@XmlType(name = "PersistentAppAction", propOrder = {
    "functions"
})
public class PersistentAppAction extends AppAction implements Action {
	private OpenProcObject procObject;
	@XmlElement(required=false)
	protected List<ProcInvocation> functions;

    /**
     * Gets the value of the functions property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the functions property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getFunctions().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link ProcInvocation }
     * 
     * 
     */
    public List<ProcInvocation> getFunctions() {
        if (functions == null) {
            functions = new ArrayList<ProcInvocation>();
        }
        return this.functions;
    }
	public PersistentAppAction(ProcInvocation proc){
		super(proc);
		functions = new ArrayList<ProcInvocation>();
	}
	public PersistentAppAction(){
		super();
	}
	public AppActionResult invoke() throws BenchmarkException{
		AppActionResult result = new AppActionResult();
		try {
			Date start = new Date();
			procObject = procInvocation.createPO(appObject);
			Thread.sleep(50);
			for(ProcInvocation proc : functions){
				proc.run(procObject);
			}
			/*try{
				if(paramArray.getOutputParameter(0) instanceof ResultSet){
					ResultSet rs = (ResultSet)paramArray.getOutputParameter(0);
					ResultSetMetaData m = rs.getMetaData();
					while(rs.next()){
						String str = "";
						for(int i = 0; i <m.getColumnCount();i++) str += rs.getObject(i+1).toString()+"; ";
						log.trace(str);
					}
				
				}
			}catch(Exception e){log.error("error",e);}*/
			long execTime = (new Date()).getTime() - start.getTime();
			result.setSuccessful(true);
			result.setTime(execTime);
		} catch (Exception e) {
			throw new BenchmarkException(
					"Error invoking procedure: " + procInvocation.getProcName(), e);
		}finally{
			try{
			if(procObject!=null) procObject._release();
			}catch(Exception e){}
		}
		return result;
	}

	public OpenProcObject getProcObject() {
		return procObject;
	}
	public void setProcObject(OpenProcObject procObject) {
		this.procObject = procObject;
	}
	public void setContext(Map<String, Object> context) {
		this.context = context;
		this.getProcInvocation().setContext(context);
		for(ProcInvocation p : functions){
			p.setContext(context);
		}
	}


}
