/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.claflin.finder.algo.clustering.struct.fast_greedy_struct;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.PriorityQueue;

/**
 *
 * @author Cesar Martin
 */
public class IndexedHeapQueue
{
	private PriorityQueue<IndexedHeapNode> q;

	public IndexedHeapQueue()
	{
		q = new PriorityQueue<>();
	}

	public int size()
	{
		return q.size();
	}

	public boolean isEmpty()
	{
		return q.isEmpty();
	}

	public void add(int i, int j, double a)
	{
		q.add(new IndexedHeapNode(i, j, a));
	}

	public IndexedHeapNode peek()
	{
		return q.peek();
	}

	public IndexedHeapNode poll()
	{
		return q.poll();
	}

	/**
	 * Replace nodes in the queue with their counterparts
	 * in a given list, according to row number (i).
	 * 
	 * @param nodes the new Nodes
	 */
	public void replaceNodes(List<IndexedHeapNode> nodes)
	{
		/*
		 * The key idea is to move out the queue until
		 * all nodes to replace are out, and then adding
		 * back in while replacing the old nodes.
		 */
		
		List<IndexedHeapNode> toReAdd = new ArrayList<>(); // stores nodes to add back in

		while (!q.isEmpty() && !nodes.isEmpty())
		{
			IndexedHeapNode qnode = q.poll();

			// find node to replace
			Optional<IndexedHeapNode> olnode = nodes.stream().filter(n -> n.getI() == qnode.getI()).findFirst();
			IndexedHeapNode lnode = olnode.isPresent() ? olnode.get() : null;

			if (lnode != null) // found a node to replace
			{
				nodes.removeIf(n -> n.getI() == lnode.getI()); // remove it from the list
				toReAdd.add(lnode); // add it back in in place of the old one
			}
			else // this node has no replacement
			{
				toReAdd.add(qnode); // add it back again
			}
		}
		q.addAll(toReAdd); // re-add nodes
	}

	@Override
	public String toString()
	{
		return q.toString();
	}
}
