package org.opentripplanner.analyst;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.google.common.collect.Lists;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * A histogram summing/counting all time values into 1-minute bins (0-60 seconds = min 1, 61-120 = min 2, etc.)
 */
public class Histogram implements Serializable {

    /**
     * Counts of accessible features in a given bin.
     * For example, value 0 is 0-1 minutes, value 50 is 50-51 minutes, etc.
     */
    public final int[] counts;
    
    /**
     * Sums of accessible features in a given bin.
     * For example, value 0 is 0-1 minutes, value 50 is 50-51 minutes, etc.
     */
    public final int[] sums;

    // TODO allow specifying breaks

    /**
     * Represent the distribution of the given times using n+1 numbers.
     * @param times the time at which each destination is reached. The array will be sorted in place.
     * @param weights the weight or magnitude of each destination reached. parallel to times.
     */
    public Histogram (int[] times, int[] weights) {
       
    	int tmpCounts[] = new int[1000];
    	int tmpSums[] = new int[1000];
    	
    	int uppperBound = 0;
    	
    	for(int i = 0; i < times.length; i++) {
    		
    		if(times[i] < 0 || times[i] == Integer.MAX_VALUE)
    			continue;
    	
    		int minuteBin = (int) Math.floor(times[i] / 60.0);
    		
    		tmpCounts[minuteBin] += 1; 
    		tmpSums[minuteBin] += weights[i];
    				
    		if(minuteBin > uppperBound)
    			uppperBound = minuteBin;
    	}
    	
    	counts = new int[uppperBound];
    	sums = new int[uppperBound];

    	for(int i = 0; i < uppperBound; i++) {
    		counts[i] = tmpCounts[i];
    		sums[i] = tmpSums[i];
    	}   	
    }
    
    public void writeJson(JsonGenerator jgen) throws JsonGenerationException, IOException {
    	
    	jgen.writeArrayFieldStart("sums"); {
    		for(int sum : sums) {
    			jgen.writeNumber(sum);
    		}
    	}
    	jgen.writeEndArray();
    	
    	jgen.writeArrayFieldStart("counts"); {
    		for(int count : counts) {
    			jgen.writeNumber(count);
    		}
    	}
    	jgen.writeEndArray();
    }
}

@@ -504,22 +504,26 @@
 %0A     * 
-Counts
+The number
  of acce
@@ -545,46 +545,41 @@
  in 
-a given bin.%0A     * For example, value
+each one-minute bin.%0A     * Index
  0 i
@@ -585,37 +585,37 @@
 is 0-1 minutes, 
-value
+index
  50 is 50-51 min
@@ -617,32 +617,252 @@
 1 minutes, etc.%0A
+%09 * The features are not weighted by their magnitudes, so values represent (for example) the number of places of%0A%09 * employment that can be reached rather than the total number of jobs in all those places of employment.%0A
      */%0A    publ
@@ -908,16 +908,32 @@
   * 
-S
+The weighted s
 um
-s
  of 
+all 
 acce
@@ -955,46 +955,38 @@
  in 
-a given bin.%0A     * For example, value
+each one-minute bin.%0A%09 * Index
  0 i
@@ -1000,21 +1000,21 @@
 inutes, 
-value
+index
  50 is 5
@@ -1036,81 +1036,242 @@
 tc.%0A
-     */%0A    public final int%5B%5D sums;%0A%0A    // TODO allow specifying breaks
+%09 * Features are weighted by their magnitudes, so values represent (for example) the total number of jobs in%0A%09 * all accessible places of employment, rather than the number of places of employment.%0A     */%0A    public final int%5B%5D sums;
 %0A%0A  
@@ -1608,20 +1608,45 @@
 ) %7B%0A
-       %0A    
+%0A%09%09// FIXME Hard coded array sizes.%0A%09
 %09int

clarify the difference between sums and counts