package org.plenix.jsp.language.ecmascript;

import FESI.jslib.*;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

import org.plenix.jsp.JspServlet;
import org.plenix.jsp.ResourceManager;
import org.plenix.jsp.Util;
import org.plenix.jsp.language.*;

public class ESProgram
{
  private String fileName;

  private String[] extensions;
  private JSGlobalObject pageEvaluator;

  private String script;
  private Vector evaluatorPool;

  private static String initScript;

  protected ESProgram(String theFileName, String[] theExtensions)
    throws JSException, IOException
  {
    this.fileName = theFileName;
    this.extensions = theExtensions;

    // Page-level evaluator initialization
    if (initScript == null)
    {
      initScript = ResourceManager.getResourceContents("evaluatorInit.es");
    }

    this.pageEvaluator = JSUtil.makeEvaluator(this.extensions);
    this.pageEvaluator.eval(initScript);

    this.script = Util.getFileContents(this.fileName);
    this.pageEvaluator.eval(this.script);

    // Evaluator pool initialization
    this.evaluatorPool = new Vector();
    this.evaluatorPool.addElement(new ESEvaluator(this.pageEvaluator, this.extensions));
  }

  protected String getFileName()
  {
    return this.fileName;
  }

  protected void execute(HttpServletRequest request, HttpServletResponse response)
    throws JSException, IOException
  {
    ESEvaluator requestEvaluator = null;
    int poolSize = evaluatorPool.size();

    int count = 0;
    for (count = 0; count < poolSize; count++)
    {
      requestEvaluator = (ESEvaluator) evaluatorPool.elementAt(count);

      if (requestEvaluator.acquire())
      {
        break;
      }
    }

    if (count == poolSize)
    {
      requestEvaluator = new ESEvaluator(this.pageEvaluator, this.extensions);

      requestEvaluator.acquire();
      this.evaluatorPool.addElement(requestEvaluator);
    }

    JSGlobalObject requestGlobalObject = requestEvaluator.getGlobalObject();

    try
    {
      // Initialize object model
      requestGlobalObject.setMember("page", requestGlobalObject.makeObjectWrapper(this.pageEvaluator));

      requestGlobalObject.setMember("servlet", requestGlobalObject.makeObjectWrapper(JspServlet.getServlet()));

      requestGlobalObject.setMember("request", requestGlobalObject.makeObjectWrapper(request));
      requestGlobalObject.setMember("input", requestGlobalObject.makeObjectWrapper(request.getReader()));
      requestGlobalObject.setMember("session", requestGlobalObject.makeObjectWrapper(request.getSession(true)));

      requestGlobalObject.setMember("response", requestGlobalObject.makeObjectWrapper(response));
      requestGlobalObject.setMember("output", requestGlobalObject.makeObjectWrapper(response.getWriter()));

      // Collect parameters
      JSObject parameters = requestGlobalObject.makeJSObject();
      JSObject requestParameters = requestGlobalObject.makeJSObject();
  
      Hashtable parsedParameters = getParameters(request);
  
      if (parsedParameters != null)
      {
        for (Enumeration e = parsedParameters.keys(); e.hasMoreElements(); )
        {
          String parameterName = (String) e.nextElement();
          String[] parameterValues = (String[]) parsedParameters.get(parameterName);
    
  	if (parameterValues.length == 1)
  	{
            parameters.setMember(parameterName, parameterValues[0]);
  	}
  	else
  	{
            parameters.setMember(parameterName, parameterValues);
  	}
  
          requestParameters.setMember(parameterName, parameterValues);
        }
      }
  
      requestGlobalObject.setMember("parameters", parameters);
      requestGlobalObject.setMember("requestParameters", requestParameters);


      // Do it!
      requestGlobalObject.evalAsFunction("service(request, response);");
    }
    finally
    {
      requestEvaluator.release();
    }
  }

  private Hashtable getParameters(HttpServletRequest request)
  {
    try
    {
      if (request.getMethod().equalsIgnoreCase("post"))
      {
          int length = request.getContentLength();
          ServletInputStream input = request.getInputStream();
  
          return HttpUtils.parsePostData(length, input);
      }
      else if (request.getMethod().equalsIgnoreCase("get"))
      {
        String queryString = request.getQueryString();
  
        return HttpUtils.parseQueryString(queryString);
      }
    }
    catch (Exception e) { }

    return null;
  }
}
