package com.stapleslabs.tree;

import java.util.List;
import java.util.Set;

/**
 * Created by timbrooks on 4/28/15.
 */
public class Forest1 implements Forest<Integer, double[]> {

    private final int[] features;
    private final double[] values;
    private final boolean[] leafIndicators;
    private final int[] offsets;
    private final double[] cutPoints;
    private final int[] roots;
    private final SpecializedCondition condition;

    public Forest1(int[] features, double[] values, boolean[] leafIndicators, int[] offsets, double[] cutPoints,
                   int[] roots, SpecializedCondition condition) {
        this.features = features;
        this.values = values;
        this.leafIndicators = leafIndicators;
        this.offsets = offsets;
        this.cutPoints = cutPoints;
        this.roots = roots;
        this.condition = condition;
    }

    public double[] reduceToValues(double[] features) {
        double[] values = new double[roots.length];
        for (int i = 0; i < roots.length; i++) {
            values[i] = traverseSingleTree(roots[i], features);
        }
        return values;
    }

    @Override
    public Forest<Integer, double[]> reduceToForest(double[] features, Set<Integer> missingFeatures) {
        throw new UnsupportedOperationException("Not allowed");
    }

    @Override
    public double[][] optimizedReduceToValues(List<double[]> features, Set<Integer> differingFeatures) {
        throw new UnsupportedOperationException("Not allowed");
    }

    @Override
    public int[] getRoots() {
        return roots;
    }

    @Override
    public Node<Integer, double[]>[] getNodes() {
        throw new UnsupportedOperationException("Not allowed");
    }

    public static <C> Forest1 createFromForest(Forest<Integer, C> forest, double[] cutPoints) {
        int maxChildren = 2;

        Node<Integer, C>[] nodes = forest.getNodes();

        int[] features = new int[nodes.length];
        double[] values = new double[nodes.length];
        boolean[] leafIndicators = new boolean[nodes.length];
        int[] offsets = new int[nodes.length * maxChildren];
        int[] roots = forest.getRoots();
        int i = 0;
        for (Node<Integer, C> node : nodes) {
            features[i] = node.feature;
            values[i] = node.value;
            leafIndicators[i] = node.isLeaf;
            int[] childOffsets = node.childOffsets;
            int j = 0;
            for (int childOffset : childOffsets) {
                offsets[(i * maxChildren) + j] = childOffset;
                ++j;
            }
            ++i;
        }
        return new Forest1(features, values, leafIndicators, offsets, cutPoints, roots, new SpecializedCondition());
    }

    private double traverseSingleTree(int root, double[] features) {
        int node = root;
        while (!leafIndicators[node]) {
            double cutPoint = cutPoints[node];
            int childOffset = condition.childOffset(cutPoint, this.features[node], features);
            int offset = (childOffset == 0) ? offsets[node * 2] : offsets[node * 2 + 1];
            node = root + offset;
        }
        return values[node];
    }


}

@@ -325,46 +325,8 @@
 ts;%0A
-    private final double%5B%5D cutPoints;%0A
     
@@ -496,32 +496,25 @@
 ffsets, 
-double%5B%5D cutPoin
+int%5B%5D roo
 ts,%0A    
@@ -527,29 +527,16 @@
         
- int%5B%5D roots,
  Special
@@ -708,44 +708,8 @@
 ts;%0A
-        this.cutPoints = cutPoints;%0A
     
@@ -1698,28 +1698,8 @@
 rest
-, double%5B%5D cutPoints
 ) %7B%0A
@@ -2556,19 +2556,8 @@
 ets,
- cutPoints,
  roo
@@ -2760,24 +2760,21 @@
 Point = 
-cutPoint
+value
 s%5Bnode%5D;

Store cutpoints in values array