package com.alvazan.orm.layer0.base;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

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

	private static final Logger log = LoggerFactory.getLogger(CursorRow.class);

	private MetaClass<T> meta;
	private String query;
	private AbstractCursor<KeyValue<Row>> cursor;
	private NoSqlSession session;
	
	public CursorRow(NoSqlSession session, MetaClass<T> meta2, AbstractCursor<KeyValue<Row>> cursor,
			String query2) {
		this.session = session;
		this.meta = meta2;
		this.cursor = cursor;
		this.query = query2;
	}

	@Override
	public void beforeFirst() {
		cursor.beforeFirst();
	}
	
	
	@Override
	public void afterLast() {
		cursor.afterLast();
	}
	
	@Override
	public Holder<KeyValue<T>> nextImpl() {
		Holder<KeyValue<Row>> nextImpl = cursor.nextImpl();
		if(nextImpl == null)
			return null;
		KeyValue<Row> kv = nextImpl.getValue();
		
		KeyValue<T> result = translateRow(kv);
		return new Holder<KeyValue<T>>(result);
	}
	
	@Override
	public Holder<KeyValue<T>> previousImpl() {
		Holder<KeyValue<Row>> prevImpl = cursor.previousImpl();
		if(prevImpl == null)
			return null;
		KeyValue<Row> kv = prevImpl.getValue();
		
		KeyValue<T> result = translateRow(kv);
		return new Holder<KeyValue<T>>(result);
	}
	
	@SuppressWarnings("rawtypes")
	private KeyValue<T> translateRow(KeyValue<Row> kv) {
		Row row = kv.getValue();
		Object key = kv.getKey();
		
		KeyValue<T> keyVal;
		if(row == null) {
			keyVal = new KeyValue<T>();
			MetaIdField idMeta = meta.getIdField();
			byte[] nonVirtKey = idMeta.unformVirtRowKey((byte[]) key);
			Object obj = meta.getIdField().translateFromBytes(nonVirtKey);
			if(query != null) {
				//for now, log the exception, but do not set it in the keyVal.  This prevents a corrupted index from 
				//breaking all queries that use that index.
				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);
				log.warn("Not erroring out, just a warning, there is an index pointing to a non-existant row.  Either the index is corrupt, or the data is not yet consistent, but might be eventually", exc);
			}
			keyVal.setKey(obj);
		} else {
			keyVal = meta.translateFromRow(row, session);
		}
		
		return keyVal;
	}

	@Override
	public String toString() {
		String tabs = StringLocal.getAndAdd();
		String retVal = "CursorRow(rowToEntity)["+tabs+cursor+tabs+"]";
		StringLocal.set(tabs.length());
		return retVal;
	}
	
}

@@ -2521,16 +2521,39 @@
 ant row.
+  The index is %22+obj+%22.
   Either

add debug output