package eu.dnetlib.r2d2.neo4j.dao;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.ReturnableEvaluator;
import org.neo4j.graphdb.TraversalPosition;
import org.neo4j.graphdb.Traverser;
import org.neo4j.graphdb.Traverser.Order;

import com.google.common.collect.Iterables;

import eu.dnetlib.r2d2.neo4j.Neo4jBean;
import eu.dnetlib.r2d2.neo4j.domain.Neo4jItem;
import eu.dnetlib.r2d2.neo4j.domain.Relationships;
import eu.dnetlib.r2d2.neo4j.util.DepthStopEvaluator;

public class Neo4jItemDao extends Neo4JDao<Neo4jItem> implements ItemDao {

	public Neo4jItemDao() {
		super(Relationships._ITEMS, Relationships._ITEM, Neo4jItem.class
				.getName());
	}

	@Override
	protected Neo4jItem createBean() {
		return new Neo4jItem();
	}

	@Override
	public Neo4jItem getItemForEntry(String entryId) {
		Iterable<Neo4jItem> iter = this.findRelatedNodes(entryId, Relationships.ITEM_ENTRY);
		
		return Iterables.getOnlyElement(iter, null);
	}

	@Override
	public void setItemForEntry(String itemId, String entryId) {
		Neo4jItem item = this.getItemForEntry(entryId);
		
		if (item != null) {
			this.removeRelationship(itemId, entryId, Relationships.ITEM_ENTRY);
		}
		
		if (itemId != null)
			this.createRelationship(itemId, entryId, Relationships.ITEM_ENTRY);
	}
	
	@Override
	public Iterable<Neo4jItem> getItemsInReadingList(String rlId) {
		Node rlNode = this.getNode(rlId);
		
		@SuppressWarnings("deprecation")
		Traverser tr = rlNode.traverse(
				Order.DEPTH_FIRST, new DepthStopEvaluator(2),
				new ReturnableEvaluator() {
					public boolean isReturnableNode(TraversalPosition pos) {
						
						if (pos.depth() > 0) {
							Node node = pos.currentNode();
	
							String type = (String) node.getProperty(Neo4jBean.PREFIX, null);
							
							return type.equals(Neo4jItem.class.getName());
						}
						
						return false;
					}
				},
				Relationships.ENTRY, Direction.INCOMING, 
				Relationships.ITEM_ENTRY, Direction.INCOMING);
		
		return new BeanIterable(tr);
	}
}