/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package TestRest.service;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.text.SimpleDateFormat;
import java.util.Date;
import TestRest.QuakemlView;
import TestRest.QuakemlViewNG;
import TestRest.Assocaro;
import TestRest.Assocamo;
import com.sun.jersey.api.core.ResourceContext;
import TestRest.converter.QuakemlViewsConverter;

/**
 *
 * @author aparnab
 */
@Path("/events/query")
public class QueryResource {
    @Context
    protected UriInfo uriInfo;
    @Context
    protected ResourceContext resourceContext;

    public QueryResource(){
    }

    /**
     * Get method for retrieving a collection of QuakemlView instance in XML format.
     *
     * @return an instance of QuakemlViewsConverter
     */
    @GET
    @Produces({"application/xml", "application/json"})
    public QuakemlViewsConverter get(
    @QueryParam("startdate")    @DefaultValue("0")    String startdate,
    @QueryParam("enddate")    @DefaultValue("10")    String enddate,
    @QueryParam("latlower")    @DefaultValue("999")    float latlower,
    @QueryParam("latupper")    @DefaultValue("999")    float latupper,
    @QueryParam("lonlower")    @DefaultValue("999")    float lonlower,
    @QueryParam("lonupper")    @DefaultValue("999")    float lonupper,
    @QueryParam("magmin")    @DefaultValue("-1")    float magmin,
    @QueryParam("magmax")    @DefaultValue("-1")    float magmax,
    @QueryParam("depthmin")    @DefaultValue("-1")    float depthmin,
    @QueryParam("depthmax")    @DefaultValue("-1")    float depthmax,
    @QueryParam("latcenter")    @DefaultValue("999")    float latcenter,
    @QueryParam("loncenter")    @DefaultValue("999")    float loncenter,
    @QueryParam("radius")    @DefaultValue("-1")    float radius,
    @QueryParam("evid")    @DefaultValue("-1")    int evid,
    @QueryParam("arid")    @DefaultValue("-1")    int arid,
    @QueryParam("latest")   @DefaultValue("-1")   int latest,
    @QueryParam("expandLevel")    @DefaultValue("1")    int expandLevel,
    @QueryParam("query")    @DefaultValue("SELECT e FROM QuakemlView e where e.etype in ('le','st')")
    String query) {
        PersistenceService persistenceSvc = PersistenceService.getInstance();
        try {
            persistenceSvc.beginTx();
            if (latlower != 999){
                return new QuakemlViewsConverter(getEntities(startdate, enddate, latlower, 
                        latupper, lonlower, lonupper, magmin, magmax, query),
                        uriInfo.getAbsolutePath(), expandLevel);
            } else if ((depthmin != -1) && (radius == -1)){
                return new QuakemlViewsConverter(getEntities(startdate, enddate, magmin, magmax,
                        depthmin, depthmax, query),
                        uriInfo.getAbsolutePath(), expandLevel);
            } else if (radius != -1){
                return new QuakemlViewsConverter(getEntities(startdate, enddate, magmin, magmax,
                        depthmin, depthmax, latcenter, loncenter, radius, query),
                        uriInfo.getAbsolutePath(), expandLevel);
            } else if(evid != -1){
                return new QuakemlViewsConverter(getEntities(evid, query), uriInfo.getAbsolutePath(), expandLevel);
            //} else if(arid != -1){
            //    return new PicksConverter(getPickEntities(arid, query), uriInfo.getAbsolutePath());
            //} else {
            } else if (startdate.compareTo("0") !=0 ){
                return new QuakemlViewsConverter(getEntities(startdate, enddate, query), uriInfo.getAbsolutePath(), expandLevel);
            } else {
                return new QuakemlViewsConverter(getEntities(query), uriInfo.getAbsolutePath(), expandLevel);
            }
        } finally {
            persistenceSvc.commitTx();
            persistenceSvc.close();
        }
    }

    //events for a range of dates
    //protected Collection<QuakemlView> getEntities(String startdate, String enddate, String query) {
    protected Collection<QuakemlViewNG> getEntities(String startdate, String enddate, String query) {
        Long startseconds = 0L, endseconds = 0L;
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        try{
            startseconds = formatter.parse(startdate).getTime()/1000;
            endseconds = formatter.parse(enddate).getTime()/1000;
        } catch (Exception e){
            e.printStackTrace();
        }
        //return em.createQuery(query).setFirstResult(start).setMaxResults(max).getResultList();
        List<QuakemlViewNG> vng = new ArrayList<QuakemlViewNG>();
        query = query + " and e.datetime between :startdate and :enddate";
        Query q = em.createQuery(query).setParameter("startdate", startseconds).setParameter("enddate", endseconds);
        System.out.println("startseconds = " + startseconds);
        System.out.println("endseconds = " + endseconds);
        List rs = q.getResultList();
        Iterator i = rs.listIterator();
        while (i.hasNext())
        {
            QuakemlViewNG temp = new QuakemlViewNG();
            QuakemlView v = (QuakemlView) i.next();
            temp.setEventEntity(v);
            //Long orid = v.getPrefor();
            //System.out.println("results = " + orid);
            //get picks for event
            //Query p = em.createNamedQuery("Assocaro.findByOrid").setParameter("orid",orid);
            //temp.setPickEntity(p.getResultList());
            temp.setPickEntity(new ArrayList<Assocaro>());

            //get amps for event
            //Query a = em.createNamedQuery("Assocamo.findByOrid").setParameter("orid", orid);
            //temp.setAmplitudeEntity(a.getResultList());
            //System.out.println("number of amplitudes" + a.getResultList().size());
            temp.setAmplitudeEntity(new ArrayList<Assocamo>());
            vng.add(temp);
        }
        return vng;
    }
    /*
    protected Collection<QuakemlViewNG> getEntities(String startdate, String enddate, String query) {
        Long startseconds = 0L, endseconds = 0L;
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        try{
            startseconds = formatter.parse(startdate).getTime()/1000;
            endseconds = formatter.parse(enddate).getTime()/1000;
        } catch (Exception e){
            e.printStackTrace();
        }
        //return em.createQuery(query).setFirstResult(start).setMaxResults(max).getResultList();
        query = query + " and e.datetime between :startdate and :enddate";
        Query q = em.createQuery(query).setParameter("startdate", startseconds).setParameter("enddate", endseconds);
        System.out.println("startseconds = " + startseconds);
        System.out.println("endseconds = " + endseconds);
        return em.createQuery(query).setParameter("startdate", startseconds).setParameter("enddate", endseconds).getResultList();
    }*/

    //events for date mag location
    protected Collection<QuakemlViewNG> getEntities(String startdate, String enddate,
            float latlower, float latupper, float lonlower, float lonupper,
            float magmin, float magmax, String query) {
        Long startseconds = 0L, endseconds = 0L;
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        try{
            startseconds = (formatter.parse(startdate).getTime()/1000) - (8 * 60 * 60);
            endseconds = (formatter.parse(enddate).getTime()/1000) - (8 * 60 * 60);
        } catch (Exception e){
            e.printStackTrace();
        }
        List<QuakemlViewNG> vng = new ArrayList<QuakemlViewNG>();
        query = query + " and e.datetime between :startdate and :enddate " +
                "and e.lat between :latlower and :latupper and e.lon between :lonlower and :lonupper " +
                "and e.magnitude between :magmin and :magmax";
        Query q = em.createQuery(query).setParameter("startdate", startseconds).setParameter("enddate", endseconds);
        q.setParameter("latlower", latlower);
        q.setParameter("latupper", latupper);
        q.setParameter("lonlower", lonlower);
        q.setParameter("lonupper", lonupper);
        q.setParameter("magmin", magmin);
        q.setParameter("magmax", magmax);
        List rs = q.getResultList();
        System.out.println("number of results = " + rs.size());
        Iterator i = rs.listIterator();
        while (i.hasNext())
        {
            QuakemlViewNG temp = new QuakemlViewNG();
            QuakemlView v = (QuakemlView) i.next();
            temp.setEventEntity(v);

            //get picks for event
            //Query p = em.createNamedQuery("Assocaro.findByOrid").setParameter("orid",orid);
            //temp.setPickEntity(p.getResultList());
            temp.setPickEntity(new ArrayList<Assocaro>());
            //Long orid = v.getPrefor();
            //System.out.println("results = " + orid);
            //get amps for event
            //Query a = em.createNamedQuery("Assocamo.findByOrid").setParameter("orid", orid);
            //temp.setAmplitudeEntity(a.getResultList());
            //System.out.println("number of amplitudes" + a.getResultList().size());
            temp.setAmplitudeEntity(new ArrayList<Assocamo>());
            vng.add(temp);
        }
        return vng;
    }
    //protected Collection<QuakemlView> getEntities(String startdate, String enddate,
    /*
    protected Collection<QuakemlViewNG> getEntities(String startdate, String enddate,
            float latlower, float latupper, float lonlower, float lonupper,
            float magmin, float magmax, String query) {
        Long startseconds = 0L, endseconds = 0L;
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        try{
            startseconds = (formatter.parse(startdate).getTime()/1000) - (8 * 60 * 60);
            endseconds = (formatter.parse(enddate).getTime()/1000) - (8 * 60 * 60);
        } catch (Exception e){
            e.printStackTrace();
        }
        query = query + " and e.datetime between :startdate and :enddate " + 
                "and e.lat between :latlower and :latupper and e.lon between :lonlower and :lonupper " +
                "and e.magnitude between :magmin and :magmax";
        Query q = em.createQuery(query).setParameter("startdate", startseconds).setParameter("enddate", endseconds);
        System.out.println("startseconds = " + startseconds);
        System.out.println("endseconds = " + endseconds);
        System.out.println("magmin = " + magmin);
        System.out.println("magmax = " + magmax);
        q.setParameter("latlower", latlower);
        q.setParameter("latupper", latupper);
        q.setParameter("lonlower", lonlower);
        q.setParameter("lonupper", lonupper);
        q.setParameter("magmin", magmin);
        q.setParameter("magmax", magmax);
        System.out.println("number of results = " + q.getResultList().size());
        return q.getResultList();
    }*/

    //events for a polygon
    protected Collection<QuakemlViewNG> getEntities(String startdate, String enddate,
            float magmin, float magmax, float depthmin, float depthmax, String query) {
        Long startseconds = 0L, endseconds = 0L;
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        try{
            startseconds = (formatter.parse(startdate).getTime()/1000) - (8 * 60 * 60);
            endseconds = (formatter.parse(enddate).getTime()/1000) - (8 * 60 * 60);
        } catch (Exception e){
            e.printStackTrace();
        }
        query = query + " and e.datetime between :startdate and :enddate " +
                "and e.magnitude between :magmin and :magmax and "+
                "e.depth between :depthmin and :depthmax";
        Query q = em.createQuery(query).setParameter("startdate", startseconds).setParameter("enddate", endseconds);
        q.setParameter("magmin", magmin);
        q.setParameter("magmax", magmax);
        q.setParameter("depthmin", depthmin);
        q.setParameter("depthmax", depthmax);
        List<QuakemlViewNG> vng = new ArrayList<QuakemlViewNG>();
        List rs = q.getResultList();
        System.out.println("number of results = " + rs.size());
        Iterator i = rs.listIterator();
        while (i.hasNext())
        {
            QuakemlViewNG temp = new QuakemlViewNG();
            QuakemlView v = (QuakemlView) i.next();
            temp.setEventEntity(v);

            //get picks for event
            //Query p = em.createNamedQuery("Assocaro.findByOrid").setParameter("orid",orid);
            //temp.setPickEntity(p.getResultList());
            temp.setPickEntity(new ArrayList<Assocaro>());
            //Long orid = v.getPrefor();
            //System.out.println("results = " + orid);
            //get amps for event
            //Query a = em.createNamedQuery("Assocamo.findByOrid").setParameter("orid", orid);
            //temp.setAmplitudeEntity(a.getResultList());
            //System.out.println("number of amplitudes" + a.getResultList().size());
            temp.setAmplitudeEntity(new ArrayList<Assocamo>());
            vng.add(temp);
        }
        return vng;
    }
    //protected Collection<QuakemlView> getEntities(String startdate, String enddate,
    /*
    protected Collection<QuakemlViewNG> getEntities(String startdate, String enddate,
            float magmin, float magmax, float depthmin, float depthmax, String query) {
        Long startseconds = 0L, endseconds = 0L;
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        try{
            startseconds = (formatter.parse(startdate).getTime()/1000) - (8 * 60 * 60);
            endseconds = (formatter.parse(enddate).getTime()/1000) - (8 * 60 * 60);
        } catch (Exception e){
            e.printStackTrace();
        }
        query = query + " and e.datetime between :startdate and :enddate " +
                "and e.magnitude between :magmin and :magmax and "+
                "e.depth between :depthmin and :depthmax";
        Query q = em.createQuery(query).setParameter("startdate", startseconds).setParameter("enddate", endseconds);
        System.out.println("startseconds = " + startseconds);
        System.out.println("endseconds = " + endseconds);
        System.out.println("magmin = " + magmin);
        System.out.println("magmax = " + magmax);
        q.setParameter("magmin", magmin);
        q.setParameter("magmax", magmax);
        q.setParameter("depthmin", depthmin);
        q.setParameter("depthmax", depthmax);
        System.out.println("number of results = " + q.getResultList().size());
        return q.getResultList();
    }*/

    //events for radius
    protected Collection<QuakemlViewNG> getEntities(String startdate, String enddate,
            float magmin, float magmax, float depthmin, float depthmax,
            float latcenter, float loncenter, float radius, String query) {
        Long startseconds = 0L, endseconds = 0L;
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        try{
            startseconds = (formatter.parse(startdate).getTime()/1000) - (8 * 60 * 60);
            endseconds = (formatter.parse(enddate).getTime()/1000) - (8 * 60 * 60);
        } catch (Exception e){
            e.printStackTrace();
        }

        String sql = "select * from quakeml where etype = 'le' and " +
                "datetime between " + startseconds + " and " + endseconds +
                " and magnitude between " + magmin + " and " + magmax +
                " and depth between " + depthmin + " and " + depthmax +
                " and wheres.separation_km(" + latcenter + "," + loncenter + "," + "lat, lon) <= " + radius;
        System.out.println("sql = " + sql);
        Query q = em.createNativeQuery(sql, QuakemlView.class);
        //Query q = em.createNativeQuery(sql, QuakemlViewNG.class);
        List<QuakemlViewNG> vng = new ArrayList<QuakemlViewNG>();
        List rs = q.getResultList();
        System.out.println("number of results = " + rs.size());
        Iterator i = rs.listIterator();
        while (i.hasNext())
        {
            QuakemlViewNG temp = new QuakemlViewNG();
            QuakemlView v = (QuakemlView) i.next();
            temp.setEventEntity(v);

            //get picks for event
            //Query p = em.createNamedQuery("Assocaro.findByOrid").setParameter("orid",orid);
            //temp.setPickEntity(p.getResultList());
            temp.setPickEntity(new ArrayList<Assocaro>());
            //Long orid = v.getPrefor();
            //System.out.println("results = " + orid);
            //get amps for event
            //Query a = em.createNamedQuery("Assocamo.findByOrid").setParameter("orid", orid);
            //temp.setAmplitudeEntity(a.getResultList());
            //System.out.println("number of amplitudes" + a.getResultList().size());
            temp.setAmplitudeEntity(new ArrayList<Assocamo>());
            vng.add(temp);
        }
        return vng;
    }
    //protected Collection<QuakemlView> getEntities(String startdate, String enddate,
    /*
    protected Collection<QuakemlViewNG> getEntities(String startdate, String enddate,
            float magmin, float magmax, float depthmin, float depthmax,
            float latcenter, float loncenter, float radius, String query) {
        Long startseconds = 0L, endseconds = 0L;
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        try{
            startseconds = (formatter.parse(startdate).getTime()/1000) - (8 * 60 * 60);
            endseconds = (formatter.parse(enddate).getTime()/1000) - (8 * 60 * 60);
        } catch (Exception e){
            e.printStackTrace();
        }
    
        String sql = "select * from quakeml where etype = 'le' and " +
                "datetime between " + startseconds + " and " + endseconds +
                " and magnitude between " + magmin + " and " + magmax +
                " and depth between " + depthmin + " and " + depthmax +
                " and wheres.separation_km(" + latcenter + "," + loncenter + "," + "lat, lon) <= " + radius;
        System.out.println("sql = " + sql);
        Query q = em.createNativeQuery(sql, QuakemlView.class);
        //Query q = em.createNativeQuery(sql, QuakemlViewNG.class);
        System.out.println("startseconds = " + startseconds);
        System.out.println("endseconds = " + endseconds);
        System.out.println("magmin = " + magmin);
        System.out.println("magmax = " + magmax);
        System.out.println("number of results = " + q.getResultList().size());
        
        return q.getResultList();
    }*/

    //events for an evid
    //protected Collection<QuakemlView> getEntities(int evid, String query) {
    protected Collection<QuakemlViewNG> getEntities(int evid, String query) {
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        /*
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        try{
            startseconds = (formatter.parse(startdate).getTime()/1000) - (8 * 60 * 60);
            endseconds = (formatter.parse(enddate).getTime()/1000) - (8 * 60 * 60);
        } catch (Exception e){
            e.printStackTrace();
        }*/
        //query = query + " and e.magnitude between :magmin and :magmax and e.depth between :depthmin and :depthmax";
        List<QuakemlViewNG> vng = new ArrayList<QuakemlViewNG>();
        query = query + " and e.evid = :evid";
        Query q = em.createQuery(query).setParameter("evid", evid);
        System.out.println("number of results = " + q.getResultList().size());
        List rs = q.getResultList();
        Iterator i = rs.listIterator();
        while (i.hasNext())
        {
            QuakemlViewNG temp = new QuakemlViewNG();
            QuakemlView v = (QuakemlView) i.next();
            temp.setEventEntity(v);
            Long orid = v.getPrefor();
            System.out.println("results = " + orid);
            //get picks for event
            Query p = em.createNamedQuery("Assocaro.findByOrid").setParameter("orid",orid);
            temp.setPickEntity(p.getResultList());

            //get amps for event
            Query a = em.createNamedQuery("Assocamo.findByOrid").setParameter("orid", orid);
            temp.setAmplitudeEntity(a.getResultList());
            System.out.println("number of amplitudes" + a.getResultList().size());
            vng.add(temp);
        }
        //Query p = em.createNamedQuery("Assocaro.findByArid").setParameter("orid", );
        System.out.println("number of items =" + vng.size());
        //return rs;
        return vng;
    }
    protected Collection<QuakemlViewNG> getEntities(String query) {
        EntityManager em = PersistenceService.getInstance().getEntityManager();
        
        List<QuakemlViewNG> vng = new ArrayList<QuakemlViewNG>();
        query = query + " order by e.evid ";
        Query q = em.createQuery(query);
        q.setFirstResult(0);
        q.setMaxResults(10);
        List rs = q.getResultList();
        Iterator i = rs.listIterator();
        while (i.hasNext())
        {            
            QuakemlViewNG temp = new QuakemlViewNG();
            QuakemlView v = (QuakemlView) i.next();
            temp.setEventEntity(v);
            Long orid = v.getPrefor();
         
            //get picks for event
            Query p = em.createNamedQuery("Assocaro.findByOrid").setParameter("orid",orid);
            temp.setPickEntity(p.getResultList());

            //get amps for event
            Query a = em.createNamedQuery("Assocamo.findByOrid").setParameter("orid", orid);
            temp.setAmplitudeEntity(a.getResultList());
            vng.add(temp);
            
        }        
        return vng;
    }
}
