package org.intermine.bio.web.logic;

/*
 * Copyright (C) 2002-2009 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.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.struts.action.ActionMessage;
import org.intermine.metadata.Model;
import org.intermine.model.InterMineObject;
import org.intermine.objectstore.ObjectStore;
import org.intermine.objectstore.ObjectStoreException;
import org.intermine.pathquery.Constraints;
import org.intermine.pathquery.Path;
import org.intermine.pathquery.PathQuery;
import org.intermine.web.logic.Constants;
import org.intermine.web.logic.bag.BagConverter;
import org.intermine.web.logic.config.WebConfig;
import org.intermine.web.logic.pathqueryresult.PathQueryResultHelper;
import org.intermine.web.logic.query.WebResultsExecutor;
import org.intermine.web.logic.results.WebResults;
import org.intermine.web.logic.session.SessionMethods;

/**
 * @author "Xavier Watkins"
 *
 */
public class OrthologueConverter implements BagConverter
{

    private static final Logger LOG = Logger.getLogger(OrthologueConverter.class);

    /**
     * The Constructor
     */
    public OrthologueConverter() {
        super();
    }

    /**
     * {@inheritDoc}
     */
    public WebResults getConvertedObjects (HttpSession session, String organism,
                                      List<Integer> fromList, String type)
                                      throws ObjectStoreException {
        
        ServletContext servletContext = session.getServletContext();
        Model model = ((ObjectStore) servletContext.getAttribute(Constants.OBJECTSTORE)).getModel();
        ObjectStore os = (ObjectStore) servletContext.getAttribute(Constants.OBJECTSTORE);
        WebConfig webConfig = (WebConfig) servletContext.getAttribute(Constants.WEBCONFIG);

        PathQuery q = new PathQuery(model);
        List<Path> view = PathQueryResultHelper.getDefaultView(type, model, webConfig,
                        "Gene.homologues.homologue", false);
        view = getFixedView(view);
        q.setViewPaths(view);
        
        List<InterMineObject> objectList = os.getObjectsByIds(fromList);

        // gene 
        q.addConstraint("Gene", Constraints.in(objectList));
        
        // organism 
        q.addConstraint("Gene.homologues.homologue.organism", Constraints.lookup(organism));

        // homologue.type = "orthologue"
        q.addConstraint("Gene.homologues.type", Constraints.eq("orthologue"));
        

        q.setConstraintLogic("A and B and C");
        q.syncLogicExpression("and");
        LOG.info("PATH QUERY:" + q.toXml(PathQuery.USERPROFILE_VERSION));
        WebResultsExecutor executor = SessionMethods.getWebResultsExecutor(session);

        return executor.execute(q);
    }

    /**
     * If view contains joined organism, this will make sure, that
     * organism is joined as a inner join. Else constraint on organism doesn't work.
     * @param pathQuery
     * @param joinPath
     */
    private List<Path> getFixedView(List<Path> view) {
        String invalidPath = "Gene.homologues.homologue:organism";
        String validPath = "Gene.homologues.homologue.organism";
        List<Path> ret = new ArrayList<Path>();
        for (Path path : view) {
            if (path.toString().contains(invalidPath)) {
                String newPathString = path.toString().replace(invalidPath, validPath);
                path = new Path(path.getModel(), newPathString);
            }
            ret.add(path);
        }
        return ret;
    }

    /**
     * {@inheritDoc}
     */
    public ActionMessage getActionMessage(Model model, String externalids, int convertedSize,
                                          String type, String organism)
                    throws UnsupportedEncodingException {
        PathQuery q = new PathQuery(model);

        // add columns to the output
        q.setView("Gene.primaryIdentifier, "
                  + "Gene.organism.shortName,"
                  + "Gene.homologues.homologue.primaryIdentifier,"
                  + "Gene.homologues.homologue.organism.shortName,"
                  + "Gene.homologues.type");

        // homologue.type = "orthologue"
        q.addConstraint("Gene.homologues.type", Constraints.eq("orthologue"));
        
        // organism
        q.addConstraint("Gene.organism", Constraints.lookup(organism));

        // if the XML is too long, the link generates "HTTP Error 414 - Request URI too long"
        if (externalids.length() < 4000) {
            q.addConstraint("Gene", Constraints.lookup(externalids));
        }

        q.setConstraintLogic("A and B and C");
        q.syncLogicExpression("and");

        String query = q.toXml(PathQuery.USERPROFILE_VERSION);
        String encodedurl = URLEncoder.encode(query, "UTF-8");

        String[] values = new String[]
            {
                String.valueOf(convertedSize),
                organism,
                String.valueOf(externalids.split(",").length),
                type,
                encodedurl
            };
        ActionMessage am = new ActionMessage("portal.orthologues", values);
        return am;
    }

}

@@ -4925,32 +4925,53 @@
 Constraint(%22Gene
+.homologues.homologue
 %22, Constraints.l

fix orthologue mapping query