package core.index.kdtree;

import core.index.MDIndex;
import core.index.key.MDIndexKey;
import core.utils.SchemaUtils.TYPE;

import java.util.List;

/**
 * Created by qui on 1/31/15.
 */
public class KDNode {

    private int dimension;
    private TYPE type;
    private Comparable value;
    private int numBuckets;

    private KDNode parent;
    private KDNode leftChild;
    private KDNode rightChild;

    public KDNode() {
        numBuckets = 1;
    }

    public int getParentDimension() {
        if (parent == null) {
            return -1;
        }
        return parent.dimension;
    }

    public int getNumBuckets() {
        return numBuckets;
    }

    public void setValues(int dimension, TYPE type, MDIndexKey key) {
        this.dimension = dimension;
        this.type = type;
        this.value = getValue(dimension, type, key);
    }

    private Comparable getValue(int dimension, TYPE type, MDIndexKey key) {
        switch (type) {
            case INT:
                return key.getIntAttribute(dimension);
            case LONG:
                return key.getLongAttribute(dimension);
            case FLOAT:
                return key.getFloatAttribute(dimension);
            case DATE:
                return (Comparable) key.getDateAttribute(dimension);
            case STRING:
                return key.getStringAttribute(dimension, 20);
            default:
                throw new RuntimeException("Unknown dimension type: "+type);
        }
        // TODO(qui): deal with VARCHAR somewhere
    }

    private void incrementNumBuckets() {
        this.numBuckets++;
        if (this.parent != null) {
            this.parent.incrementNumBuckets();
        }
    }

    public KDNode insert(MDIndexKey key) {
        if (value == null) {
            return this;
        } else if (value.compareTo(getValue(dimension, type, key)) > 0) {
            if (leftChild == null) {
                leftChild = new KDNode();
                leftChild.parent = this;
		this.leftChild = leftChild;
                if (rightChild == null) {
                    numBuckets = 2;
                    if (parent != null) { parent.incrementNumBuckets(); }
                }
                return leftChild;
            } else {
                return leftChild.insert(key);
            }
        } else {
            if (rightChild == null) {
                rightChild = new KDNode();
                rightChild.parent = this;
		this.rightChild = rightChild;
                if (leftChild == null) {
                    numBuckets = 2;
                    if (parent != null) { parent.incrementNumBuckets(); }
                }
                return rightChild;
            } else {
                return rightChild.insert(key);
            }
        }
    }

    public int getBucketId(MDIndexKey key, int start) {
        if (value == null) {
            return start;
        }
        Comparable searchVal = getValue(dimension, type, key);
        if (value.compareTo(searchVal) > 0) {
            if (leftChild == null) {
                return start;
            }
            return leftChild.getBucketId(key, start*2);
        }
        else {
            if (rightChild == null) {
                return start;
            }
            return rightChild.getBucketId(key, start*2+1);
        }
    }

    public List<MDIndex.Bucket> rangeSearch(MDIndexKey low, MDIndexKey high) {
        return null;
    }
}

@@ -82,16 +82,73 @@
 dexKey;%0A
+import core.utils.RangeUtils.SimpleDateRange.SimpleDate;%0A
 import c
@@ -175,16 +175,16 @@
 s.TYPE;%0A
-
 %0Aimport 
@@ -323,26 +323,22 @@
 private 
-Comparable
+Object
  value;%0A
@@ -920,26 +920,22 @@
 private 
-Comparable
+Object
  getValu
@@ -1290,21 +1290,8 @@
 turn
- (Comparable)
  key
@@ -1564,32 +1564,801 @@
 omewhere%0A    %7D%0A%0A
+    private int compareKey(Object value, int dimension, TYPE type, MDIndexKey key) %7B%0A        switch (type) %7B%0A            case INT:%0A                return ((Integer) value).compareTo(key.getIntAttribute(dimension));%0A            case LONG:%0A                return ((Long) value).compareTo(key.getLongAttribute(dimension));%0A            case FLOAT:%0A                return ((Float) value).compareTo(key.getFloatAttribute(dimension));%0A            case DATE:%0A                return ((SimpleDate) value).compareTo(key.getDateAttribute(dimension));%0A            case STRING:%0A                return ((String) value).compareTo(key.getStringAttribute(dimension, 20));%0A            default:%0A                throw new RuntimeException(%22Unknown dimension type: %22+type);%0A        %7D%0A    %7D%0A%0A
     private void
@@ -2628,33 +2628,26 @@
 if (
-value.
 compare
-To(getV
+Key(v
 alue
-(
+, 
 dime
@@ -2663,17 +2663,16 @@
 pe, key)
-)
  %3E 0) %7B%0A
@@ -2795,38 +2795,8 @@
 is;%0A
-%09%09this.leftChild = leftChild;%0A
     
@@ -3220,40 +3220,8 @@
 is;%0A
-%09%09this.rightChild = rightChild;%0A
     
@@ -3652,40 +3652,30 @@
     
-Comparable searchVal = getV
+if (compareKey(v
 alue
-(
+, 
 dime
@@ -3695,48 +3695,8 @@
 key)
-;%0A        if (value.compareTo(searchVal)
  %3E 0

Fix date comparison in KDNode