package com.alvazan.orm.layer0.base;

import java.util.Iterator;

import com.alvazan.orm.api.exc.RowNotFoundException;
import com.alvazan.orm.api.z5api.NoSqlSession;
import com.alvazan.orm.api.z8spi.AbstractCursor;
import com.alvazan.orm.api.z8spi.KeyValue;
import com.alvazan.orm.api.z8spi.Row;
import com.alvazan.orm.impl.meta.data.MetaClass;

public class CursorRow<T> extends AbstractCursor<KeyValue<T>>{

	private MetaClass<T> meta;
	private NoSqlSession session;
	private String query;
	private Integer batchSize;
	
	private Iterable<byte[]> noSqlKeys;
	private Iterator<byte[]> keysIterator;
	//TODO: lastCachedRows SHOULD be Cursor I believe....
	private AbstractCursor<KeyValue<Row>> lastCachedRows;
	
	public CursorRow(MetaClass<T> meta, Iterable<byte[]> noSqlKeys, NoSqlSession s, String query2, Integer batchSize) {
		this.meta = meta;
		this.noSqlKeys = noSqlKeys;
		this.keysIterator = noSqlKeys.iterator();
		this.session = s;
		this.query = query2;
		this.batchSize = batchSize;
	}
	
	@Override
	public void beforeFirst() {
		keysIterator = noSqlKeys.iterator();
	}
	
	@Override
	public Holder<KeyValue<T>> nextImpl() {
		fetchMoreResults();
		if(lastCachedRows == null)
			return null;
		
		KeyValue<T> row = fetchRow();
		return new Holder<KeyValue<T>>(row);
	}
	
	private void fetchMoreResults() {
		if(lastCachedRows != null && lastCachedRows.hasNext())
			return; //We have rows left so do NOT fetch results
		else if(!keysIterator.hasNext()) {
			//we know we have NO rows left in cache at this point but there are als NO 
			//keys left!!! so return and set the lastCachedRows to null
			lastCachedRows = null;
			return;
		}
		
		
		String cf = meta.getColumnFamily();		
		//If batchSize is null, we MUST use the keysIterator not iterable(just trust me or the keyIterator.hasNext up above no longer works)
		Iterable<byte[]> proxyCounting = new IterableNotCounting(this.keysIterator);
		if(batchSize != null) {
			//let's give a window of batchSize view into the iterator ;)  so it will stop at 
			//batchSize when looping over our iterator
			proxyCounting = new IterableCounting(this.keysIterator, batchSize);
		}
		boolean skipCache = query != null; //if someone is querying into, we need to skip the cache!!!
		lastCachedRows = session.findAll(cf, proxyCounting, skipCache);
	}

	private KeyValue<T> fetchRow() {
		KeyValue<Row> kv = lastCachedRows.next();
		Row row = kv.getValue();
		Object key = kv.getKey();
		
		KeyValue<T> keyVal;
		if(row == null) {
			keyVal = new KeyValue<T>();
			Object obj = meta.getIdField().translateFromBytes((byte[]) key);
			if(query != null) {
				RowNotFoundException exc = new RowNotFoundException("Your query="+query+" contained a value with a pk where that entity no longer exists in the nosql store");
				keyVal.setException(exc);
			}
			keyVal.setKey(obj);
		} else {
			keyVal = meta.translateFromRow(row, session);
		}
		
		return keyVal;
	}
	
}

@@ -596,63 +596,8 @@
 or;%0A
-%09//TODO: lastCachedRows SHOULD be Cursor I believe....%0A
 %09pri
@@ -1076,32 +1076,56 @@
 l() %7B%0A%09%09
+KeyValue%3CT%3E nextResult = 
 fetch
-More
+Next
 Result
-s
 ();%0A%09%09if
@@ -1125,30 +1125,26 @@
 );%0A%09%09if(
-lastCachedRows
+nextResult
  == null
@@ -1168,40 +1168,8 @@
 %0A%09%09%0A
-%09%09KeyValue%3CT%3E row = fetchRow();%0A
 %09%09re
@@ -1197,19 +1197,26 @@
 lue%3CT%3E%3E(
-row
+nextResult
 );%0A%09%7D%0A%09%0A
@@ -1228,29 +1228,35 @@
 ate 
-void
+KeyValue%3CT%3E
  fetch
-More
+Next
 Result
-s
 () %7B
@@ -1287,11 +1287,45 @@
 null
- &&
+) %7B%0A%09%09%09Holder%3CKeyValue%3CRow%3E%3E holder =
  las
@@ -1340,110 +1340,85 @@
 ows.
-hasNext())
+nextImpl();
 %0A%09%09%09
-return; //We have rows left so do NOT fetch results%0A%09%09else if(!keysIterator.hasNext()) %7B
+if(holder != null)%0A%09%09%09%09return translateRow(holder.getValue());
 %0A%09%09%09
@@ -1426,167 +1426,65 @@
 /we 
-know we have NO rows left in cache at this point but there are als NO %0A%09%09%09//keys left!!! so return and set the lastCachedRows to null%0A%09%09%09lastCachedRows = null;
+need to fetch more%0A%09%09%7D%0A%09%09%0A%09%09if(!keysIterator.hasNext()) %7B
 %0A%09%09%09
@@ -1489,16 +1489,21 @@
 %09%09return
+ null
 ;%0A%09%09%7D%0A%09%09
@@ -2155,16 +2155,161 @@
 Cache);%0A
+%09%09Holder%3CKeyValue%3CRow%3E%3E nextImpl = lastCachedRows.nextImpl();%0A%09%09if(nextImpl == null)%0A%09%09%09return null;%0A%09%09return translateRow(nextImpl.getValue());%0A
 %09%7D%0A%0A%09pri
@@ -2329,23 +2329,21 @@
 %3CT%3E 
-fetchRow() %7B%0A%09%09
+translateRow(
 KeyV
@@ -2358,33 +2358,11 @@
 %3E kv
- = lastCachedRows.next();
+) %7B
 %0A%09%09R

modify so we are not using hasNext which makes traversing classes a bit easier