/*  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */

package org.apache.pluto.driver.services.container;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.portlet.PortletAsyncEvent;
import javax.portlet.PortletAsyncListener;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.pluto.container.PortletInvokerService;
import org.apache.pluto.container.PortletResourceResponseContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Manages the listeners registered by the application. Releases portal resources when 
 * the async request completes and provides contextual services for the listeners. 
 * 
 * @author Scott Nicklous
 */
public class PortletAsyncContextListener implements AsyncListener {
   
   /** Logger. */
   private static final Logger LOG = LoggerFactory.getLogger(PortletAsyncContextListener.class);
   private static final boolean isDebug = LOG.isDebugEnabled();
   private static final boolean isTrace = LOG.isTraceEnabled();
   
   
   // Data for one listener
   private class Entry {

      public AsyncListener          hlis;
      public ServletRequest         hreq;
      public ServletResponse        hresp;
      public PortletAsyncListener   plis;
      public ResourceRequest        preq;
      public ResourceResponse       presp;

      public Entry(AsyncListener lis, ServletRequest req, ServletResponse resp) {
         this.hlis  = lis;
         this.hreq  = req;
         this.hresp = resp;
      }
      
      public Entry(PortletAsyncListener lis, ResourceRequest req, ResourceResponse resp) {
         this.plis  = lis;
         this.preq  = req;
         this.presp = resp;
      }
   }
   
   // The registered listeners
   List<Entry> listeners = new ArrayList<Entry>();
   
   private long start  = System.currentTimeMillis();
   private final PortletAsyncContextImpl pactx;
   
 
   public PortletAsyncContextListener(PortletAsyncContextImpl pactx) {
      this.pactx = pactx;
   }
   
   public void addListener(AsyncListener l) {
      listeners.add(new Entry(l, null, null));
   }
   
   public void addListener(AsyncListener l, ServletRequest req, ServletResponse resp) {
      listeners.add(new Entry(l, req, resp));
   }
   
   public void addListener(PortletAsyncListener l) {
      listeners.add(new Entry(l, null, null));
   }
   
   public void addListener(PortletAsyncListener l, ResourceRequest req, ResourceResponse resp) {
      listeners.add(new Entry(l, req, resp));
   }
   
   private void trace (String meth) {
      if (isTrace) {
         StringBuilder txt = new StringBuilder();
         txt.append("Firing ").append(meth).append(" event for ");
         txt.append(listeners.size()).append(" listeners.");
         int hcnt=0, pcnt=0;
         for (Entry e : listeners) {
            if (e.hlis != null) hcnt++;
            if (e.plis != null) pcnt++;
         }
         txt.append(", # AsyncListeners: ").append(hcnt);
         txt.append(", # PortletAsyncListeners: ").append(pcnt);
         LOG.trace(txt.toString());
      }
   }

   /*
    * (non-Javadoc)
    * 
    * @see javax.servlet.AsyncListener#onComplete(javax.servlet.AsyncEvent)
    */
   @Override
   public void onComplete(AsyncEvent evt) throws IOException {

      trace("onComplete");
      
      pactx.registerContext(true);
      for (Entry l : listeners) {
         if (l.hlis != null) {
            AsyncEvent lisevt = new AsyncEvent(pactx, l.hreq, l.hresp);
            l.hlis.onComplete(lisevt);
         } else {
            PortletAsyncEvent lisevt = new PortletAsyncEvent(pactx, l.preq, l.presp);
            l.plis.onComplete(lisevt);
         }
      }
      pactx.deregisterContext(true);
      pactx.setComplete(true);
      
      long delta = System.currentTimeMillis() - start;
      StringBuilder txt = new StringBuilder(128);
      txt.append("Completed. Execution time: ").append(delta).append(" milliseconds.");
      txt.append(" Releasing: ");

      HttpServletRequest hreq = (HttpServletRequest) evt.getSuppliedRequest();
      if (hreq != null) {
         ResourceRequest rreq = (ResourceRequest) hreq.getAttribute(PortletInvokerService.PORTLET_REQUEST);
         if (rreq != null) {

            // remove portlet-scoped barnacles

            txt.append("portlet-scoped attributes; ");
            rreq.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
            rreq.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
            rreq.removeAttribute(PortletInvokerService.PORTLET_CONFIG);
            rreq.removeAttribute(PortletInvokerService.ASYNC_METHOD);

            PortletResourceResponseContext respctx = (PortletResourceResponseContext) rreq
                  .getAttribute(PortletInvokerService.RESPONSE_CONTEXT);
            if (respctx != null) {
               txt.append("response context resources; ");
               respctx.close();
               respctx.release();
            }
         } else {
            txt.append("... no resource request stuff. Couldn't get resource request; ");
         }
         
         // remove container-scoped attributes

         txt.append("container-scoped attributes; ");
         hreq.removeAttribute(PortletInvokerService.METHOD_ID);
         hreq.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
         hreq.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
         hreq.removeAttribute(PortletInvokerService.FILTER_MANAGER);

      } else {
         txt.append("... no servlet request stuff. Couldn't get servlet request.");
      }
      
      txt.append(" Removing contextual info.");
      pactx.removeContext();

      if (isDebug) {
         LOG.debug(txt.toString());
      }

   }

   /*
    * (non-Javadoc)
    * 
    * @see javax.servlet.AsyncListener#onError(javax.servlet.AsyncEvent)
    */
   @Override
   public void onError(AsyncEvent evt) throws IOException {
      
      trace("onError");      
      pactx.registerContext(true);
      for (Entry l : listeners) {
         if (l.hlis != null) {
            AsyncEvent lisevt = new AsyncEvent(pactx, l.hreq, l.hresp);
            l.hlis.onError(lisevt);
         } else {
            PortletAsyncEvent lisevt = new PortletAsyncEvent(pactx, l.preq, l.presp);
            l.plis.onError(lisevt);
         }
      }
      pactx.deregisterContext(true);
      
      long delta = System.currentTimeMillis() - start;
      StringBuilder txt = new StringBuilder(128);
      txt.append("Error after ").append(delta).append(" milliseconds.");

      // attempt to complete

      try {
         AsyncContext ctx = evt.getAsyncContext();
         ctx.complete();
         txt.append(" Portlet container completed request processing on behalf of the application.");
      } catch (IllegalStateException e) {
         txt.append(" An earlier listener has already dispatched or completed request.");
      } catch (Exception e) {
      }

      txt.append(", Exception: ").append(evt.getThrowable().getMessage());
      if (isDebug) {
         LOG.debug(txt.toString());
      }
   }

   /*
    * (non-Javadoc)
    * 
    * @see javax.servlet.AsyncListener#onStartAsync(javax.servlet.AsyncEvent)
    */
   @Override
   public void onStartAsync(AsyncEvent evt) throws IOException {

      trace("onStartAsync");
      
      // copy & clear the original listener list. If a listener wants to be notified
      // again, it will add itself again.
      
      ArrayList<Entry> entries = new ArrayList<Entry>(listeners);
      listeners.clear();

      pactx.registerContext(true);
      for (Entry l : entries) {
         if (l.hlis != null) {
            AsyncEvent lisevt = new AsyncEvent(pactx, l.hreq, l.hresp);
            l.hlis.onStartAsync(lisevt);
         } else {
            PortletAsyncEvent lisevt = new PortletAsyncEvent(pactx, l.preq, l.presp);
            l.plis.onStartAsync(lisevt);
         }
      }
      pactx.deregisterContext(true);
      
      long delta = System.currentTimeMillis() - start;
      StringBuilder txt = new StringBuilder(128);
      txt.append("Async started again after ").append(delta).append(" milliseconds.");
      if (isDebug) {
         LOG.debug(txt.toString());
      }

      // need to add this listener again so it gets called when finally complete.

      AsyncContext ctx = evt.getAsyncContext();
      ctx.addListener(this);
   }

   /*
    * (non-Javadoc)
    * 
    * @see javax.servlet.AsyncListener#onTimeout(javax.servlet.AsyncEvent)
    */
   @Override
   public void onTimeout(AsyncEvent evt) throws IOException {

      trace("onTimeout");
      
      pactx.registerContext(true);
      for (Entry l : listeners) {
         if (l.hlis != null) {
            AsyncEvent lisevt = new AsyncEvent(pactx, l.hreq, l.hresp);
            l.hlis.onTimeout(lisevt);
         } else {
            PortletAsyncEvent lisevt = new PortletAsyncEvent(pactx, l.preq, l.presp);
            l.plis.onTimeout(lisevt);
         }
      }
      pactx.deregisterContext(true);
      
      long delta = System.currentTimeMillis() - start;
      StringBuilder txt = new StringBuilder(128);
      txt.append("Timeout after ").append(delta).append(" milliseconds.");
      
      // if the application has properly registered a listener and has not processed the 
      // timeout by calling onComplete or dispatch, complete the request.
      
      boolean warn = false;
      AsyncContext ctx = evt.getAsyncContext();
      try {
         ctx.getRequest();
         
         try {
            ctx.complete();
            txt.append(" Portlet container completed request processing on behalf of the application.");
            warn = true;
         } catch (IllegalStateException e) {
            txt.append(" An earlier listener has dispatched again.");
         } catch (Exception e) {
            txt.append(" Exception occured while completing request: " + e.toString());
         }
         
      } catch(Exception e) {
         txt.append(" Async processing was completed by the application.");
      }

      if (warn) {
         LOG.warn(txt.toString());
      } else {
         if (isDebug) {
            LOG.debug(txt.toString());
         }
      }
   }

}
