package com.indent.actions.portlets;

import org.apache.jetspeed.portal.portlets.AbstractInstancePortlet;
//jetspeed
import org.apache.jetspeed.capability.CapabilityMap;
import org.apache.jetspeed.capability.CapabilityMapFactory;
import org.apache.jetspeed.om.registry.MediaTypeEntry;
import org.apache.jetspeed.om.registry.PortletEntry;
import org.apache.jetspeed.portal.BasePortletConfig;
import org.apache.jetspeed.portal.expire.Expire;
import org.apache.jetspeed.portal.expire.ExpireFactory;
import org.apache.jetspeed.portal.Portlet;
import org.apache.jetspeed.portal.PortletConfig;
import org.apache.jetspeed.portal.PortletException;
import org.apache.jetspeed.portal.PortletState;
import org.apache.jetspeed.services.persistence.PersistenceManager;
import org.apache.jetspeed.services.persistence.PortalPersistenceException;
import org.apache.jetspeed.portal.PortletInstance;
import org.apache.jetspeed.services.portletcache.Cacheable;
import org.apache.jetspeed.services.Registry;
import org.apache.jetspeed.util.JetspeedException;
import org.apache.jetspeed.util.MetaData;
import org.apache.jetspeed.util.MimeType;

//ecs
import org.apache.jetspeed.util.JetspeedClearElement;
import org.apache.ecs.ConcreteElement;
import org.apache.ecs.ElementContainer;

//turbine stuff
import org.apache.turbine.services.cache.CachedObject;
import org.apache.turbine.services.cache.Refreshable;
import org.apache.turbine.util.Log;
import org.apache.turbine.util.RunData;
import java.net.*;
import java.io.*;
import java.util.*;
import com.ai.application.utils.*;
import com.ai.aspire.utils.*;

import org.apache.jetspeed.services.Profiler;
import org.apache.jetspeed.om.profile.ProfileLocator;

import org.apache.jetspeed.util.*;
import org.apache.jetspeed.util.template.*;


// Turbine Classes
import org.apache.turbine.util.Log;
import org.apache.turbine.util.DynamicURI;
import org.apache.turbine.services.jsp.JspService;
import org.apache.turbine.util.TurbineException;

// ECS support
import org.apache.ecs.ConcreteElement;
import org.apache.ecs.StringElement;

// Jetspeed support
import org.apache.jetspeed.services.rundata.JetspeedRunData;
import org.apache.jetspeed.om.profile.ProfileLocator;
import org.apache.jetspeed.om.profile.Profile;
import org.apache.jetspeed.services.Profiler;
import org.apache.jetspeed.util.template.JetspeedLink;
import org.apache.jetspeed.util.template.JetspeedLinkFactory;

import org.apache.turbine.util.*;
import org.apache.turbine.util.upload.*;

import java.util.*;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.*;
import com.ai.htmlgen.*;
import com.ai.application.interfaces.*;
import com.ai.common.*;

//******************************************************************************
//* Start of the class
//******************************************************************************
/**
 * Goal:
 * 1. Here is a url paint it.
 * 2. First time make up a url
 * 3.
 */
public class AspirePortlet  extends AbstractInstancePortlet
{
//******************************************************************************
//* getContent: Main entry point. Only public method
//******************************************************************************
   public ConcreteElement getContent(RunData rundata)
   {
      ConcreteElement ce=null;
      AspireContent ac = null;
      //See if you need to get it from cache
      if (isThisTheFirstURL(rundata) == true)
      {
         //first time
         ac= getRealContent(rundata,true);
         cacheContent(ac,rundata);
      }
      else
      {
         //Not the first time
         boolean bCache = this.doYouNeedCache(rundata);
         if (bCache == true)
         {
            //Give out the cache
            AppObjects.log("Info.SP:Going to deliver cache");
            ac= getCachedContent(rundata);
            if (ac instanceof URLAspireContent)
            {
               ce=new JetspeedClearElement(ac.content);
            }
            else
            {
               //jsp content
               try {this.processCachedJSPPage(ac.jspTemplate,rundata); }
               catch(Exception x){AppObjects.log("Error:sever jsp exception",x);}
               ce = new ElementContainer();
            }
         }
         else
         {
            //Give out the real non-cached content
            AppObjects.log("Info.SP:This is not the first time. This is not the cache");
            ac = getRealContent(rundata,false);
            cacheContent(ac,rundata);
            if (ac instanceof URLAspireContent)
            {
               ce = new JetspeedClearElement(ac.content);
            }
            else
            {
               ce = new ElementContainer();
            }
         }
      }
      return ce;
   }//eof-function

//******************************************************************************
//* cacheContent
//******************************************************************************
   private void cacheContent(AspireContent value,RunData rundata)
   {
      PortletSessionState.setAttribute(this,rundata,"content",value);
   }
//******************************************************************************
//* getCachedContent
//******************************************************************************
   private AspireContent getCachedContent(RunData rundata)
   {
      return (AspireContent)PortletSessionState.getAttribute(this,rundata,"content");
   }

//******************************************************************************
//* getRealContent
//******************************************************************************
   public AspireContent getRealContent(RunData rundata, boolean firstTime)
   {
      //contributorsURL
      try
      {
         AspireContent finalContent = null;

         //Get hashtable of params
         Hashtable params = this.getURLParameters(rundata);

         //Append the selflink
         String selfLink = this.getSelfLink(rundata);
         AppObjects.log("Info.SP:Placing aspire_jetspeed_selflink:" + selfLink + " in hashtable");
         params.put("aspire_jetspeed_selflink",selfLink);

         //See if this is the first url
         if (firstTime == true)
         {
            //this is the first url
            finalContent = this.getContentForURL("contributorsURL",params,rundata);
         }
         else
         {
            String url = (String)params.get("url");
            if (url != null)
            {
               //display case
               finalContent = this.getContentForURL(url,params,rundata);
            }
            else
            {
               //update case
               String requestName = (String)params.get("request_name");
               String redirectURL = executeRequestForURL(requestName, params);
               finalContent = this.getContentForURL(url,params,rundata);
            }
         }
         return finalContent;
      }
      catch(Exception x)
      {
         AppObjects.log("Error:",x);
         return new URLAspireContent("SOrry there is an error");
      }
   }//eof-function

   private String executeRequestForURL(String requestName, Hashtable params)
         throws com.ai.application.interfaces.ConfigException
   {
      try
      {
         AppObjects.getObject(requestName,params);
         String redirectURL = AppObjects.getValue("request." + requestName + ".redirectURL");
         return redirectURL;
      }
      catch(com.ai.application.interfaces.RequestExecutionException x)
      {
         AppObjects.log("Warn:web request failed",x);
         String failureRedirectURL = AppObjects.getValue("request." + requestName + ".failureRedirectURL");
         return failureRedirectURL;
      }

   }//eof-function erfu

//******************************************************************************
//* getContentForURL
//******************************************************************************
   private AspireContent getContentForURL(String url, Hashtable params, RunData rundata)
         throws com.ai.common.TransformException
   {

         String transformType = AppObjects.getValue(url + ".transformType",null);
      try
      {
         if (transformType == null)
         {
            //content type is going to be url
            String x = TransformUtils.transform(url,params);
            return new URLAspireContent(x);
         }
         //transformtype is mentioned
         //assume it is jsp for now
         String jspPageName = AppObjects.getValue(url + ".template"
               ,AppObjects.getValue(url));

         AppObjects.log("Info.js:Processing jsp page:" + jspPageName);
         processJSPPage(url,jspPageName,params,rundata);
         return new JSPAspireContent(jspPageName);
      }
      catch(com.ai.application.interfaces.ConfigException x)
      {
         throw new com.ai.common.TransformException("Error:Could not read the jsp template",x);
      }
      catch(javax.servlet.ServletException x)
      {
         throw new com.ai.common.TransformException("Error:servlet exception",x);
      }
      catch(java.io.IOException x)
      {
         throw new com.ai.common.TransformException("Error.js:io exception",x);
      }
      catch(RequestExecutionException x)
      {
         throw new com.ai.common.TransformException("Error.js:RequestExecution exception",x);
      }
   }//eof-function

//******************************************************************************
//* processJSPPage
//******************************************************************************
   private void processJSPPage(String url, String jspPageName, Hashtable params, RunData rundata)
         throws RequestExecutionException, java.io.IOException, javax.servlet.ServletException
   {
      //Get the action object from aspire
      Object dataObj = FormUtils.getDataObjectFor(url,params);


      HttpServletRequest request = rundata.getRequest();

      //Set it in the rundata or request
      request.setAttribute("AspireDataSet",dataObj);

      // Allow access to portlet from .jsp template
      request.setAttribute("portlet", this);

      // Add js_peid out of convenience
      request.setAttribute("js_peid", getID());

      // Add rundata out of convenience (JspService.RUNDATA differs from GenericMVCPortlet.RUNDATA)
      request.setAttribute(JspService.RUNDATA, rundata);


      //Set addition fields in the request
      //call the jsp
      // get the RequestDispatcher for the JSP
      RequestDispatcher dispatcher = rundata.getServletContext().getRequestDispatcher(jspPageName);
      rundata.getOut().flush();
      dispatcher.include(rundata.getRequest(), rundata.getResponse());

   }

   private void processCachedJSPPage(String jspPageName, RunData rundata)
         throws RequestExecutionException, java.io.IOException, javax.servlet.ServletException
   {

      HttpServletRequest request = rundata.getRequest();

      // Allow access to portlet from .jsp template
      request.setAttribute("aspire_jsp_deliver_cache", "true");

      // Allow access to portlet from .jsp template
      request.setAttribute("portlet", this);

      // Add js_peid out of convenience
      request.setAttribute("js_peid", getID());

      // Add rundata out of convenience (JspService.RUNDATA differs from GenericMVCPortlet.RUNDATA)
      request.setAttribute(JspService.RUNDATA, rundata);


      //Set addition fields in the request
      //call the jsp
      // get the RequestDispatcher for the JSP
      RequestDispatcher dispatcher = rundata.getServletContext().getRequestDispatcher(jspPageName);
      rundata.getOut().flush();
      dispatcher.include(rundata.getRequest(), rundata.getResponse());

   }

//******************************************************************************
//* getStringForURL
//******************************************************************************
   private String getStringForURL(String url, Hashtable params)
         throws com.ai.common.TransformException
   {

      String x = TransformUtils.transform(url,params);
      return x;
   }

//******************************************************************************
//* readFromAURL
//******************************************************************************
   private String readFromAURL()
   {
      BufferedReader br = null;
      try
      {
         //get a url
         URL url = new URL("http://216.187.231.34/akc/index.html");
         URLConnection con = url.openConnection();


         br = new BufferedReader ( new
           InputStreamReader(con.getInputStream()));

         String line = "";
         StringBuffer buf = new StringBuffer();
         while ((line = br.readLine()) != null)
           buf.append(line);

         return buf.toString();
      }
      catch(Exception x)
      {
         AppObjects.log("Error:",x);
         return "Sorry there is an error";
      }
      finally
      {
         if (br != null)
            try {br.close();}catch (Exception x){}
         }
   }
//******************************************************************************
//* getSelfLink
//******************************************************************************
   private String getSelfLink(RunData indata)
         throws TurbineException
   {
	//see what the current action is
	String action = rundata.getParameters.getString("action");
	if (action == null)
	{
		action = "controls.Maximize";
	}

      JetspeedRunData data = (JetspeedRunData)indata;
      ProfileLocator baseLocator = Profiler.createLocator();
      baseLocator.createFromPath(data.getProfile().getPath());
      AppObjects.log("action:" + data.getAction());
      JetspeedLink link = JetspeedLinkFactory.getInstance(data);
      DynamicURI uri = link.getLink(JetspeedLink.CURRENT,
                                    "",
                                    baseLocator.getName(),
                                    JetspeedLink.PORTLET_ID,
                                    this.getID(),
                                    action,
                                    null,
                                    baseLocator.getMediaType(),
                                    baseLocator.getLanguage(),
                                    baseLocator.getCountry());

      String result = uri.toString();
      JetspeedLinkFactory.putInstance(link);
      return result;
   }//eof-function

//******************************************************************************
//* getURLParameters
//******************************************************************************
   private Hashtable getURLParameters(RunData rundata)
   {
      Hashtable ht = new Hashtable();
      ParameterParser pp = rundata.getParameters();
      Enumeration keys = pp.keys();
      while (keys.hasMoreElements())
      {
         String key = (String)keys.nextElement();
         String value = pp.get(key);
         AppObjects.log("Info.SP: Adding key " + key + ":" + value);
         ht.put(key,value);
      }
      ht.put("aspire_turbine_rundata",rundata);
      return ht;
   }//eof-function


//******************************************************************************
//* getStringForURL
//******************************************************************************
   private boolean isThisTheFirstURL(RunData rundata)
   {
      Object value=PortletSessionState.getAttribute(this,rundata,"active");
      if (value != null)
      {
         //It is active
         return false;
      }
      AppObjects.log("Info.SP:This is the first time for this portlet:" + this.getID());
      PortletSessionState.setAttribute(this,rundata,"active","true");
      return true;
   }
//******************************************************************************
//* getStringForURL
//******************************************************************************
   /**
    * Caching should address multiple cases.
    * Case 0: Drill down
    *    . If I am not the target I need the cache
    * Case 1: restore/maximize
    *    . I am the target
    *    . But I don't have any parms because I got the call because of a maximize or restore
    *    . The fact that I don't have any params I am expecting is an indication of such an activity
    */
   private boolean doYouNeedCache(RunData rundata)
   {
      AspireContent ac = (AspireContent)this.getCachedContent(rundata);
      if (ac == null)
      {
         return false;
      }
      if (amITheTarget(rundata) == false)
      {
         //I am not the target
         return true;
      }
      //This will cover restore/maximize case
      String url = rundata.getParameters().get("url");
      String requestName = rundata.getParameters().get("request_name");

      if (url == null && requestName == null) return true;
      return false;

   }

//******************************************************************************
//* getStringForURL
//******************************************************************************
   private boolean amITheTarget(RunData rundata)
   {
      String myPeid = this.getID();
      AppObjects.log("Info:myPeid=" + myPeid);
      String inPeid = rundata.getParameters().get("js_peid");
      if (inPeid == null)
      {
         //There is no incoming peid
         AppObjects.log("Info:There is no incoming peid");
         return false;
      }
      AppObjects.log("Info:incoming peid=" + inPeid);
      //peid exists
      if (myPeid.equals(inPeid))
      {
         // the peids match
         return true;
      }
      return false;
   }//eof-function
//******************************************************************************
//* getFirstPageForThisPortlet
//******************************************************************************

	public String getFirstPageURLForThisPortlet()
	{
		String porletName = this.getName();
		String firstURL = AppObjects.log("portlet-entry." + portletName + ".firstURL");
		AppObjects.log("Info.js: First url for portlet " + portletName + " is " + firstURL);
		return firstURL;
	}//eof-function
}//eof-class

//******************************************************************************
//* Internal classes in this package. Could be internal to the class.
//******************************************************************************
class AspireContent
{
   public String content;
   public String jspTemplate;
   public String contentType;
   public AspireContent(String inContent, String inContentType, String inJSPTemplate)
   {
      content=inContent;
      contentType = inContentType;
      jspTemplate = inJSPTemplate;
   }
}

class URLAspireContent extends AspireContent
{
      public URLAspireContent(String content)
      {
         super(content,"url",null);
      }
}

class JSPAspireContent extends AspireContent
{
   public JSPAspireContent(String jspTemplate)
   {
      super(null,"jsp",jspTemplate);
   }
}