package org.antlr.codebuff.misc;

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;

public class BuffUtils {

	public static int indexOf(ParserRuleContext parent, ParseTree child) {
		for (int i = 0; i<parent.getChildCount(); i++) {
			if ( parent.getChild(i)==child) {
				return i;
			}
		}
		return -1;
	}

	//  Generic filtering, mapping, joining that should be in the standard library but aren't
	public static <T> T findFirst(List<T> data, Predicate<T> pred) {
		if ( data!=null ) for (T x : data) {
			if ( pred.test(x) ) {
				return x;
			}
		}
		return null;
	}

	public static <T> List<T> filter(List<T> data, Predicate<T> pred) {
		List<T> output = new ArrayList<>();
		if ( data!=null ) for (T x : data) {
			if ( pred.test(x) ) {
				output.add(x);
			}
		}
		return output;
	}

	public static <T> List<T> filter(Collection<T> data, Predicate<T> pred) {
		List<T> output = new ArrayList<>();
		for (T x : data) {
			if ( pred.test(x) ) {
				output.add(x);
			}
		}
		return output;
	}

	public static <T,R> List<R> map(Collection<T> data, Function<T,R> getter) {
		List<R> output = new ArrayList<>();
		if ( data!=null ) for (T x : data) {
			output.add(getter.apply(x));
		}
		return output;
	}

	public static <T,R> List<R> map(T[] data, Function<T,R> getter) {
		List<R> output = new ArrayList<>();
		if ( data!=null ) for (T x : data) {
			output.add(getter.apply(x));
		}
		return output;
	}

	public static double variance(List<Integer> data) {
		int n = data.size();
		double sum = 0;
		double avg = sum(data) / ((double)n);
		for (int d : data) {
			sum += (d-avg)*(d-avg);
		}
		return sum / n;
	}

	public static double varianceFloats(List<Float> data) {
		int n = data.size();
		double sum = 0;
		double avg = sumFloats(data) / ((double)n);
		for (float d : data) {
			sum += (d-avg)*(d-avg);
		}
		return sum / n;
	}

	public static int sum(List<Integer> data) {
		int sum = 0;
		for (int d : data) {
			sum += d;
		}
		return sum;
	}

	public static float sumFloats(List<Float> data) {
		float sum = 0;
		for (float d : data) {
			sum += d;
		}
		return sum;
	}

	public static List<Double> diffFloats(List<Float> a, List<Float> b) {
		List<Double> diffs = new ArrayList<>();
		for (int i = 0; i<a.size(); i++) {
			diffs.add((double)a.get(i) - b.get(i));
		}
		return diffs;
	}

}

@@ -172,24 +172,54 @@
 Collection;%0A
+import java.util.Collections;%0A
 import java.
@@ -481,24 +481,25 @@
 ld(i)==child
+ 
 ) %7B%0A%09%09%09%09retu
@@ -1231,32 +1231,33 @@
 ublic static %3CT,
+ 
 R%3E List%3CR%3E map(C
@@ -1278,32 +1278,33 @@
 ata, Function%3CT,
+ 
 R%3E getter) %7B%0A%09%09L
@@ -1452,16 +1452,17 @@
 atic %3CT,
+ 
 R%3E List%3C
@@ -1489,16 +1489,17 @@
 ction%3CT,
+ 
 R%3E gette
@@ -1751,27 +1751,25 @@
  = sum(data)
- / 
+/
 ((double)n);
@@ -1757,32 +1757,33 @@
 (data)/((double)
+ 
 n);%0A%09%09for (int d
@@ -1828,35 +1828,33 @@
 %09%09%7D%0A%09%09return sum
- / 
+/
 n;%0A%09%7D%0A%0A%09public s
@@ -1972,19 +1972,17 @@
 ts(data)
- / 
+/
 ((double
@@ -1982,16 +1982,17 @@
 (double)
+ 
 n);%0A%09%09fo
@@ -2059,11 +2059,9 @@
  sum
- / 
+/
 n;%0A%09
@@ -2086,20 +2086,26 @@
 int sum(
-List
+Collection
 %3CInteger
@@ -2214,28 +2214,34 @@
 t sumFloats(
-List
+Collection
 %3CFloat%3E data
@@ -2496,16 +2496,17 @@
 ble)
+ 
 a.get(i)
  - b
@@ -2505,11 +2505,9 @@
 t(i)
- - 
+-
 b.ge
@@ -2537,10 +2537,285 @@
 fs;%0A%09%7D%0A%0A
+%09public static Double median(List%3CDouble%3E data) %7B%0A%09%09Collections.sort(data);%0A%09%09int n = data.size();%0A%09%09return data.get(n/2);%0A%09%7D%0A%0A%09public static Double mean(Collection%3CDouble%3E data) %7B%0A%09%09double sum = 0.0;%0A%09%09for (Double d : data) %7B%0A%09%09%09sum += d;%0A%09%09%7D%0A%09%09return sum / data.size();%0A%09%7D%0A
 %7D%0A

add median, mean