package models.transit;



import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.ManyToOne;
import javax.persistence.Query;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.PrecisionModel;

import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.Type;

import play.db.jpa.Model;
import utils.EncodedPolylineBean;
import utils.PolylineEncoder;

@Entity
public class TripShape extends Model {
	
    public String gtfsShapeId;
    public String description;
    
    public Double describedDistance;
    
    @ManyToOne
    public Agency agency;
    
    @Type(type = "org.hibernatespatial.GeometryUserType") 
    public LineString shape;
    
    @Type(type = "org.hibernatespatial.GeometryUserType") 
    public LineString simpleShape;
    

    public void updateShapeFromEncoded(String encoded) {
        
        String linestring = generateLinestring(encoded);

        TripShape.em().createNativeQuery("UPDATE tripshape SET shape = ST_GeomFromText( ?, 4326) WHERE id = ?;")
            .setParameter(1,  linestring)
            .setParameter(2,  this.id)
            .executeUpdate();
        
        this.refresh();
    }

    public String generateEncoded() {
        
        EncodedPolylineBean ecb = PolylineEncoder.createEncodings(shape);
        
        return ecb.getPoints();
    }

    public static TripShape createFromEncoded(String encoded) {
    	
        
    	BigInteger tripShapeId = TripShape.nativeInsert(TripShape.em(), "", generateLinestring(encoded), 0.0);

        return TripShape.findById(tripShapeId.longValue());
    }

    public static TripShape createFromPattern(TripPattern tp) {
    	
    	List<String> points = new ArrayList<String>();
        for(TripPatternStop tps : tp.patternStops) {
        
            points.add(new Double(tps.stop.locationPoint().getX()).toString() + " " + new Double(tps.stop.locationPoint().getY()).toString());
        }
        
        if(points.size() > 0) {
        	String linestring = "LINESTRING(" + StringUtils.join(points, ", ") + ")";
        	
        	
        	BigInteger tripShapeId = TripShape.nativeInsert(TripShape.em(), "", linestring, 0.0);

            return TripShape.findById(tripShapeId.longValue());
        }
        else 
        	return null;
        
    }
    
    public static String generateLinestring(String encoded) {
        
        EncodedPolylineBean ecb = new EncodedPolylineBean(encoded, null, 0);
        List<Coordinate> coords = PolylineEncoder.decode(ecb);
        
        List<String> points = new ArrayList<String>();
        for(Coordinate coord : coords) {
            points.add(new Double(coord.y).toString() + " " + new Double(coord.x).toString());
        }
        
        String linestring = "LINESTRING(" + StringUtils.join(points, ", ") + ")";

        return linestring;
    }

    public static BigInteger nativeInsert(EntityManager em, String shapeId, String shape, Double distance)
    {
    	Query idQuery = em.createNativeQuery("SELECT NEXTVAL('hibernate_sequence');");
    	BigInteger nextId = (BigInteger)idQuery.getSingleResult();
    	
        em.createNativeQuery("INSERT INTO tripshape (id, gtfsshapeid, shape, describeddistance)" +
        	"  VALUES(?, ?, ST_GeomFromText( ?, 4326), ?);")
          .setParameter(1,  nextId)
          .setParameter(2,  shapeId)	            
          .setParameter(3,  shape)
          .setParameter(4,  distance)
          .executeUpdate();
        
        return nextId;
    }
   
}

@@ -77,16 +77,46 @@
 ayList;%0A
+import java.util.Collections;%0A
 import j
@@ -1969,32 +1969,84 @@
 List%3CString%3E();%0A
+    %09%0A    %09Collections.sort(tp.patternStops);%0A    %09%0A
         for(Trip

add sort to trippatterns before shape