/******************************************************************************
  *  Name:    Reference Solution
  *  NetID:   ref
  *  Precept: P00
  *
  *  Description:  Reads GPS tracking data (lat, lon, alt) and creates a 
  *                Path of waypoints.  After reading in data, computes and
  *                prints stats.  Stats are based on a command line argument
  *                threshold.
  ******************************************************************************/

public class Path {
    
    private Node first;   // a reference to the "first" node on the tour
    private Node last;   // a reference to the "last" node on the tour
    
    // a node in the circular linked list
    private static class Node {
        private Coordinate coord;
        private Node next;
    }
    
    // create an empty trip
    public Path() { }
    
    // return a string representation of this tour
    public String toString() {
        if (first == null) return "";
        StringBuilder sb = new StringBuilder();
        Node x = first;
        do {
            sb.append(x.coord + "\n");
            x = x.next;
        } while (x != first);
        return sb.toString();
    }
    
    // return Stats regarding the path
    public Stats computeStats(int altThresh) {
        if (first == null) 
            return new Stats();
        
        double lastAlt = first.coord.getAlt();
        double high = lastAlt;
        double low = lastAlt;
        int points = 1;
        double dist = 0.0;
        double asc = 0.0;
        double desc = 0.0;
        
        if (last == first) 
            return new Stats(points, dist, high, low, asc, desc);
        
        Node x = first;
        do {
            Node next = x.next;
            points++;
            dist += x.coord.haversineDist(next.coord);
            if (Math.abs(lastAlt - next.coord.getAlt()) > altThresh) {
                if (lastAlt > next.coord.getAlt())
                    desc += (lastAlt - next.coord.getAlt());
                else
                    asc += (next.coord.getAlt() - lastAlt);
                lastAlt = next.coord.getAlt();
            }
            x = next;
            high = Math.max(high, x.coord.getAlt());
            low = Math.min(low, x.coord.getAlt());
        } while (x != last);
        
        return new Stats(points, dist, high, low, asc, desc);
    }
    
    // insert waypoint at the end of the path
    public void addWaypoint(Coordinate coord) {
        
        Node node = new Node();
        node.coord = coord;
        
        if (first == null) {
            first = node;
            last = node;
            node.next = node;
            return;
        }
        
        last.next = node;
        node.next = first;
        last = node;
    }
    
    // main client
    public static void main(String[] args) {
        
        Path path = new Path();
        while(!StdIn.isEmpty()) {
            double lon = StdIn.readDouble();
            double lat = StdIn.readDouble();
            double alt = StdIn.readDouble();
            path.addWaypoint(new Coordinate(lon, lat, alt));
        }
        if (args.length == 0) {
            StdOut.print(path);
            return;
        } else if (args.length == 1) {
            int thresh = Integer.parseInt(args[0]);
            StdOut.print(path.computeStats(thresh));
            return;
        }
        
        StdOut.println("ERROR: Path takes zero or one command line argument.");
    }
}