package org.intermine.web;

/*
 * Copyright (C) 2002-2005 FlyMine
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  See the LICENSE file for more
 * information or http://www.gnu.org/copyleft/lesser.html.
 *
 */

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.intermine.model.InterMineObject;
import org.intermine.web.results.PagedTable;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

/**
 * Repeatedly poll the status of a running query and forward client to appropriate page
 * each time.
 * 
 * @see org.intermine.web.QueryMonitor
 * @see org.intermine.web.QueryMonitorTimeout
 * @see org.intermine.web.SessionMethods#runQuery
 * @author Thomas Riley
 */
public class PollQueryAction extends InterMineAction
{
    protected static final Logger LOG = Logger.getLogger(PollQueryAction.class);
    
    /**
     * Handle request from client.
     *
     * @param mapping The ActionMapping used to select this instance
     * @param form The optional ActionForm bean for this request (if any)
     * @param request The HTTP request we are processing
     * @param response The HTTP response we are creating
     * @return an ActionForward object defining where control goes next
     * @exception Exception if the application business logic throws
     *  an exception
     */
    public ActionForward execute(ActionMapping mapping,
                                 ActionForm form,
                                 HttpServletRequest request,
                                 HttpServletResponse response)
        throws Exception {
        HttpSession session = request.getSession();
        String qid = request.getParameter("qid");
        boolean followSingleResult = "followSingleResult".equals(mapping.getParameter());
        
        if (StringUtils.isEmpty(qid)) {
            recordError(new ActionMessage("errors.pollquery.emptyqid", qid), request);
            return mapping.findForward("error");
        }
        
        QueryMonitorTimeout controller = (QueryMonitorTimeout)
                SessionMethods.getRunningQueryController(qid, session);
        if (controller == null) {
            LOG.debug("invalid qid " + qid + " redirecting as if cancelled");
            return mapping.findForward("cancelled");
        }
        
        // First tickle the controller to avoid timeout
        controller.tickle();
        
        if (controller.isCancelledWithError()) {
            LOG.debug("query qid " + qid + " error");
            return mapping.findForward("failure");
        } else if (controller.isCancelled()) {
            LOG.debug("query qid " + qid + " cancelled");
            recordError(new ActionMessage("errors.pollquery.cancelled", qid), request);
            return mapping.findForward("cancelled");
        } else if (controller.isCompleted()) {
            LOG.debug("query qid " + qid + " complete");
            // Look at results, if only one result, go straight to object details page
            PagedTable pr = SessionMethods.getResultsTable(session, "results." + qid);
            if (followSingleResult && pr.getSize () == 1
                    && ((List) pr.getAllRows ().get(0)).size() == 1) {
                Object o = ((List) pr.getAllRows ().get(0)).get(0);
                if (o instanceof InterMineObject) {
                    return new ActionForward("/objectDetails.do?id="
                            + ((InterMineObject) o).getId()
                            + "&trail=_" + ((InterMineObject) o).getId(), true);
                }
            }
            return new ForwardParameters(mapping.findForward("results"))
                .addParameter("table", "results." + qid).forward();
        } else {
            LOG.debug("query qid " + qid + " still running, making client wait");
            request.setAttribute("qid", request.getParameter("qid"));
            if (controller.getTickleCount() < 4) {
                request.setAttribute("POLL_REFRESH_SECONDS", new Integer(1));
            } else {
                request.setAttribute("POLL_REFRESH_SECONDS",
                                            new Integer(Constants.POLL_REFRESH_SECONDS));
            }
            int imgnum = ((controller.getTickleCount() + 1) % 4) + 1;
            if (controller.getTickleCount() < 4) {
                request.setAttribute("imgnum", new Integer(1));
            } else {
                request.setAttribute("imgnum", new Integer(imgnum));
            }
            
            // there are different action mappings for different kinds of
            // query (portal, template, query builder) so we have to refresh
            // to the correct path
            request.setAttribute("POLL_ACTION_NAME", mapping.getPath());
            return mapping.findForward("waiting");
        }
    }
}
@@ -937,18 +937,17 @@
 time.%0A *
- 
 %0A
+
  * @see 
@@ -1237,21 +1237,17 @@
 class);%0A
-    
 %0A
+
     /**%0A
@@ -2164,25 +2164,17 @@
 ter());%0A
-        
 %0A
+
         
@@ -2347,33 +2347,25 @@
 ;%0A        %7D%0A
-        
 %0A
+
         Quer
@@ -2662,25 +2662,17 @@
       %7D%0A
-        
 %0A
+
         
@@ -2748,25 +2748,17 @@
 ckle();%0A
-        
 %0A
+
         
@@ -3483,16 +3483,19 @@
  () == 1
+) %7B
 %0A       
@@ -3507,62 +3507,70 @@
     
-    && ((List) pr.getAllRows ().get(0)).size() == 1) %7B
+// Query can have more than one column, forward from the first
 %0A   
@@ -4846,21 +4846,9 @@
   %7D%0A
-            
 %0A
+
     
@@ -5169,9 +5169,10 @@
 %7D%0A    %7D%0A
-
 %7D
+%0A

allow quick search query to have more than one column