package mauda.plugin.binqueue;

import mauda.plugin.fibheap.*;
import mauda.operation.*;

import jedas.*;
import java.awt.Color;

/**
 * <p>Title: Binomial Queue</p>
 * <p>Description: A binomial queue can be viewed as a special case of Fibonacci
 * Heaps where, after each operation, the rootlist ist consolidated.</p>
 * <p>Copyright: Copyright (c) 2003</p>
 * <p>Company: University of Freiburg -- Institute of Computer Science</p>
 * @author Tobias Lauer
 * @version 3.2.5
 */
public class BinQueue extends FibHeapExt {

	private TextObj message[];
	private DPair   messagePos[];
	private Color   messageColor[];

	public BinQueue() {
		super();
				
		FibHeap.setTextMode(FibHeap.NONE);
		FibHeap.showArray = false;
				
		this.minPointer.setColor(Color.white);
		this.minPointer.setArrowFillColor(Color.white);

		messagePos = new DPair[3];	
		messagePos[0] = new DPair(0.5, 0.85);
		messagePos[1] = new DPair(0.5, 0.90);
		messagePos[2] = new DPair(0.5, 0.95);

		messageColor = new Color[3];
		messageColor[0] = Color.RED;
		messageColor[1] = Color.BLUE;
		messageColor[2] = Color.BLACK;

		message = new TextObj[3];
		for (int i=0; i<3; i++) {
			message[i] = new TextObj("",
									messagePos[i],
									14,
									TextObj.CENTER,
									TextObj.NORMAL,
									messageColor[i]);
			mainCompObj.addItem(message[i]);
		}
	}


	public FibNode insert(int k) {
		//hideMessage();
		showMessage("Insert("+k+")", 1);
		FibNode newFibNode = super.insert(k);
		consolidate();
		resetMin();
		return newFibNode;
	}

	public FibNode findmin() {
		FibNode temp = min.getRightSibling();
		FibNode last = min;
		while (temp != last) {
			if (temp.getKey() < min.getKey())
				min = temp;
			temp = temp.getRightSibling();
		}
		this.showMessage("Minimum key is "+min.getKey(),2);
		return min;
	}


	public int deletemin() {
		//hideMessage();
		showMessage("Delete_Min()", 0);
		return delete(findmin());
	}

	public int delete(FibNode node) {
		//hideMessage();
		showMessage("Delete("+node.getKey()+")", 1);
		cutTree(node);
		remove(node);
		consolidate();
		resetMin();
		return node.getKey();
		/*
		node.cut(node.getRoot());
		remove(node);
		consolidate();
		resetMin();
		return node.getKey();
		*/
	}

	public void decreasekey(FibNode FibNode, int k) {
		hideMessage();
		showMessage("Decrease key "+FibNode.getKey()+" to "+k, 0);
		delete(FibNode);
		insert(k);
	}

	void cutTree(FibNode node) {
		resetMin();
		if (!node.isRoot())
			cutTree(node.getParentNode());
		FibNode temp = node.getRightSibling();
		FibNode it;
		while (node.isLeftOf(temp)) {
			it = temp;
			temp = temp.getRightSibling();

			if(it.getKey() != it.getRoot().getKey()) {
				// SubOperation CUT
				add(new SubOperation("CUT", it.getKey()));
			}

			it.cut(it.getRoot());
			animate();
			resetMin();
		}

		if(node.getKey() != node.getRoot().getKey()) {
			// SubOperation CUT
			add(new SubOperation("CUT", node.getKey()));
		}

		node.cut(node.getRoot());
		animate();
		resetMin();
	}

	void resetMin() {
		min = getLeftmostNode().getLeftSibling();
	}

	void showMessage(String text, int level) {
		// create TextObj and place where appropriate
		//if (level==0)
		//	text = "Current operation:  "+text;
		message[level].setText(text);
		message[level].setVisible(true);
		Jedas.updateDisplay();
	}

	/**
	 * Hides the text messages.
	 */
	void hideMessage() {
		message[0].setText(""); //Visible(false);
		message[1].setText(""); //Visible(false);
		message[2].setText(""); //Visible(false);
		Jedas.updateDisplay();
	}
}
