package com.github.davidmoten.rtree.flatbuffers;

import java.util.ArrayList;
import java.util.List;

import com.github.davidmoten.rtree.Context;
import com.github.davidmoten.rtree.Entry;
import com.github.davidmoten.rtree.Leaf;
import com.github.davidmoten.rtree.LeafHelper;
import com.github.davidmoten.rtree.Node;
import com.github.davidmoten.rtree.NodeAndEntries;
import com.github.davidmoten.rtree.geometry.Geometry;
import com.github.davidmoten.rtree.geometry.Point;
import com.github.davidmoten.rtree.geometry.Rectangle;

import rx.Subscriber;
import rx.functions.Func1;

public class LeafFlatBuffers<T, S extends Geometry> implements Leaf<T, S> {

    private final Node_ node;
    private final Context<T, S> context;

    public LeafFlatBuffers(Node_ node, Context<T, S> context) {
        this.node = node;
        this.context = context;
    }

    @Override
    public List<Node<T, S>> add(Entry<? extends T, ? extends S> entry) {
        return LeafHelper.add(entry, this);
    }

    @Override
    public NodeAndEntries<T, S> delete(Entry<? extends T, ? extends S> entry, boolean all) {
        return LeafHelper.delete(entry, all, this);
    }

    @Override
    public void search(Func1<? super Geometry, Boolean> condition,
            Subscriber<? super Entry<T, S>> subscriber) {
        LeafHelper.search(condition, subscriber, this);
    }

    @Override
    public int count() {
        return node.entriesLength();
    }

    @Override
    public Context<T, S> context() {
        return context;
    }

    @Override
    public Geometry geometry() {
        Box_ b = node.mbb();
        // create on demand to reduce memory use (though not gc pressure)
        return Rectangle.create(b.minX(), b.minY(), b.maxX(), b.maxY());
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Entry<T, S>> entries() {
        List<Entry<T, S>> list = new ArrayList<Entry<T, S>>(node.entriesLength());
        for (int i = 0; i < node.entriesLength(); i++) {
            Geometry_ g = node.entries(i).geometry();
            final Geometry geometry;
            if (g.type() == GeometryType_.Box) {
                Box_ b = g.box();
                geometry = Rectangle.create(b.minX(), b.minY(), b.maxX(), b.maxY());
            } else if (g.type() == GeometryType_.Point) {
                Point_ p = g.point();
                geometry = Point.create(p.x(), p.y());
            } else
                throw new RuntimeException("unexpected");
            list.add(Entry.<T, S> entry((T) new Object(), (S) geometry));
        }
        return list;
    }

}

@@ -361,16 +361,57 @@
 ntries;%0A
+import com.github.davidmoten.rtree.Util;%0A
 import c
@@ -452,24 +452,24 @@
 y.Geometry;%0A
-
 import com.g
@@ -561,16 +561,65 @@
 ctangle;
+%0Aimport com.google.flatbuffers.FlatBufferBuilder;
 %0A%0Aimport
@@ -838,26 +838,41 @@
 Buffers(
-Node_ node
+List%3CEntry%3CT, S%3E%3E entries
 , Contex
@@ -907,51 +907,1126 @@
 his.
-node = node;%0A        this.context = context
+context = context;%0A        FlatBufferBuilder builder = new FlatBufferBuilder(0);%0A        int%5B%5D entries2 = new int%5Bentries.size()%5D;%0A        for (int i = 0; i %3C entries.size(); i++) %7B%0A            Rectangle b = entries.get(i).geometry().mbr();%0A            int box = Box_.createBox_(builder, b.x1(), b.y1(), b.x2(), b.y2());%0A            Geometry_.startGeometry_(builder);%0A            Geometry_.addBox(builder, box);%0A            Geometry_.addType(builder, GeometryType_.Box);%0A            int g = Geometry_.endGeometry_(builder);%0A            int obj = Entry_.createObjectVector(builder, new byte%5B%5D %7B 'b', 'o', 'o' %7D);%0A            entries2%5Bi%5D = Entry_.createEntry_(builder, g, obj);%0A        %7D%0A        int entries2Pointers = Node_.createEntriesVector(builder, entries2);%0A        Rectangle mbb = Util.mbr(entries);%0A        int boxPointer = Box_.createBox_(builder, mbb.x1(), mbb.y1(), mbb.x2(), mbb.y2());%0A        Node_.startNode_(builder);%0A        Node_.addMbb(builder, boxPointer);%0A        Node_.addEntries(builder, entries2Pointers);%0A        Node_.endNode_(builder);%0A        node = Node_.getRootAsNode_(builder.dataBuffer())
 ;%0A  

use FlatBuffers