package main.java.edgetype;


import java.util.Comparator;
import java.util.GregorianCalendar;

import main.java.core.State;
import main.java.core.WalkOptions;
import main.java.core.WalkResult;
import main.java.gtfs.ServiceCalendar;
import main.java.gtfs.StopTime;
import main.java.gtfs.exception.DateOutOfBoundsException;


public class Hop extends AbstractPayload implements Comparable<Hop> {
	
	public static class HopArrivalTimeComparator implements Comparator<Hop> {

		@Override
		public int compare(Hop arg0, Hop arg1) {
			Integer v1 = new Integer(arg0.end.arrival_time.getSecondsSinceMidnight());
			Integer v2 = new Integer(arg1.end.arrival_time.getSecondsSinceMidnight());
			return v1.compareTo(v2);
		}
		
	}
	
	private static final long serialVersionUID = -7761092317912812048L;
	private static final int SECS_IN_DAY = 86400;
	private static final int SECS_IN_HOUR = 3600;
	private static final int SECS_IN_MINUTE = 60;
	public StopTime start;
	public StopTime end;
	public ServiceCalendar calendar;
	private int elapsed;

	public Hop( StopTime start, StopTime end ) throws Exception {
		this.start = start;
		this.end = end;
		this.calendar = this.start.getTrip().getServiceCalendar();
		this.elapsed = end.arrival_time.getSecondsSinceMidnight() - start.arrival_time.getSecondsSinceMidnight();
	}
	
    public WalkResult walk( State state0, WalkOptions wo ) {
    	//The basic idea: find the amount of time from state0.time until the hop begins. Weight is that wait+the transit time
    	
    	GregorianCalendar serviceDay = (GregorianCalendar)state0.time.clone();
    	int secondsSinceMidnight = state0.time.get(GregorianCalendar.HOUR_OF_DAY)*SECS_IN_HOUR+
    	                           state0.time.get(GregorianCalendar.MINUTE)*SECS_IN_MINUTE+
    	                           state0.time.get(GregorianCalendar.SECOND);
    	// if the Hop's departure StopTime is more than 24 hours from midnight (say, yesterday) we don't need to check
    	// that the ServiceCalendar runs today - we need to check that it runs yesterday.
    	int overageDays = start.departure_time.getSecondsSinceMidnight()/SECS_IN_DAY;
    	serviceDay.add(GregorianCalendar.DATE, -overageDays );
    	secondsSinceMidnight += SECS_IN_DAY*overageDays;
    	
    	try {
			if(!calendar.runsOn(serviceDay)) {
				return null;
			}
		} catch (DateOutOfBoundsException ex) {
			return null;
		}
    	
    	int wait = start.departure_time.getSecondsSinceMidnight() - secondsSinceMidnight;
    	if( wait < 0 ) {
    		return null;
    	}
    	
    	State state1 = state0.clone();
    	state1.time = (GregorianCalendar)state0.time.clone();
    	state1.time.add(GregorianCalendar.SECOND, wait+elapsed);
    	return new WalkResult(wait+elapsed, state1);
    }
    
    public WalkResult walkBack( State state0, WalkOptions wo ) {
    	//The basic idea: find the amount of time from the hop arrival to state0.time. Weight is that wait+the transit time

    	GregorianCalendar serviceDay = (GregorianCalendar)state0.time.clone();
    	int secondsSinceMidnight = state0.time.get(GregorianCalendar.HOUR)*SECS_IN_HOUR+
    	                           state0.time.get(GregorianCalendar.MINUTE)*SECS_IN_MINUTE+
    	                           state0.time.get(GregorianCalendar.SECOND);
    	// if the Hop's arrival StopTime is more than 24 hours from midnight (say, yesterday) we don't need to check
    	// that the ServiceCalendar runs today - we need to check that it runs yesterday.
    	int overageDays = end.arrival_time.getSecondsSinceMidnight()/SECS_IN_DAY;
    	serviceDay.add(GregorianCalendar.DATE, -overageDays );
    	secondsSinceMidnight += SECS_IN_DAY*overageDays;
    	
    	if(!calendar.runsOn(serviceDay)) {
    		return null;
    	}
    	
    	int wait = secondsSinceMidnight - end.arrival_time.getSecondsSinceMidnight();
    	if( wait < 0 ) {
    		return null;
    	}
    	
    	State state1 = state0.clone();
    	state1.time = (GregorianCalendar)state0.time.clone();
    	state1.time.add(GregorianCalendar.SECOND, -(wait+elapsed));
    	return new WalkResult(wait+elapsed, state1);
    	
    }

	public int compareTo(Hop arg0) {
		return this.end.compareTo( arg0.end ); 
	}
	
	public String toString() {
		return this.start + " " + this.end + " " + this.calendar;
	}
	
}

@@ -2557,67 +2557,8 @@
 ();%0A
-    %09state1.time = (GregorianCalendar)state0.time.clone();%0A
     
@@ -3839,67 +3839,8 @@
 ();%0A
-    %09state1.time = (GregorianCalendar)state0.time.clone();%0A
     

Revert "hops have to clone the state time on their own"