package org.objectweb.proactive.ic2d.gui.jobmonitor.data;

import java.util.*;

import org.objectweb.proactive.ic2d.gui.jobmonitor.JobMonitorConstants;

class AssoKey implements Comparable {
	private int lkey;
	private int rkey;
	private String name;
	
	public AssoKey(int lkey, int rkey, String name) {
		this.lkey = lkey;
		this.rkey = rkey;
		this.name = name;
	}
	
	public int compareTo(Object o) {
		AssoKey a = (AssoKey) o;
		
		if (lkey != a.lkey)
			return lkey - a.lkey;
		
		if (rkey != a.rkey)
			return rkey - a.rkey;
		
		return name.compareTo(a.name);
	}
	
	public String getName() {
		return name;
	}
	
	public String toString() {
		return name + "(" + lkey + "->" + rkey + ")";
	}
}

/*
 *                     VN
 *                      |
 *                      *
 *                      |
 *                      v
 * Host -*-> JVM -*-> Node -*-> AO
 *                      ^
 *                      |
 *                      *
 *                      |
 *                     Job
 */

public class DataAssociation implements JobMonitorConstants {
	private Map asso;
	private Set[] sets;
	
	public DataAssociation() {
		clear();
	}
	
	private Set getSetForKey(int key) {
		int index = KEY2INDEX[key];
		return sets[index];
	}
	
	private void makeSet(int key) {
		int index = KEY2INDEX[key];
		sets[index] = new TreeSet();
	}
	
	private void addToSet(int key, String value) {
		int index = KEY2INDEX[key];
		if (getSetForKey(key) == null)
			makeSet(key);
		
		getSetForKey(key).add(value);
	}
	
	private void addAsso(int fromKey, String fromValue, int toKey, String toValue) {
		addToSet(toKey, toValue);
		
		AssoKey key = new AssoKey(fromKey, toKey, fromValue);
		Object res = asso.get(key);
		if (res == null) {
			res = new TreeSet();
			asso.put(key, res);
		}
		
		Set l = (Set) res;
		l.add(toValue);
	}

	public void addChild(int fromKey, String fromValue, int toKey, String toValue) {
		addAsso(fromKey, fromValue, toKey, toValue);
		addAsso(toKey, toValue, fromKey, fromValue);
	}

	/* Example : addChild(HOST, "camel.inria.fr", "PA_JVM_0123456798") */
	public void addChild(int key, String lvalue, String rvalue) {
		if (isSpecialKey(key))
			throw new RuntimeException("This key does not have any child");
		else
			addChild(key, lvalue, key + 1, rvalue);
	}

	private boolean isSpecialKey(int key) {
		for (int i = 0; i < SPECIAL_KEYS.length; i++)
			if (key == SPECIAL_KEYS[i])
				return true;

		return false;
	} 
	
	private Set getAsso(int from, String name, int to) {
		AssoKey key = new AssoKey(from, to, name);
		Object res = asso.get(key);
		if (res == null) {
			res = new TreeSet();
			asso.put(key, res);
		}
		
		return (Set) res;
	}
	
	private Set handleSpecialKey(int from, String name, int to) {
//		dumpMap();
		Set toNode;
		toNode = getValues(from, name, NODE);
		Set res = new TreeSet();
		Iterator iter = toNode.iterator();
		while (iter.hasNext()) {
			String stepName = (String) iter.next();
			Set temp = getValues(NODE, stepName, to);
			res.addAll(temp);
		}
		return res;
	}
	
	/*
	 * Exemple : getValues(VN, "myVN", AO) ==> {"Object1", "Object2"}
	 */
	public Set getValues(int from, String name, int to) {
		System.out.println(from + " - " + to);
		if (to == from) {
			Set res = new TreeSet();
			res.add(name);
			return res;
		}

		if (from == NO_KEY)
			return list(to);
		
		if (isSpecialKey(from) && to != NODE)
			return handleSpecialKey(from, name, to);
		
		if ((from == NODE || to == NODE) && (isSpecialKey(from) || isSpecialKey(to)))
			return getAsso(from, name, to);

		if (isSpecialKey(from) || isSpecialKey(to))
			return handleSpecialKey(from, name, to);
		
		if (to == from + 1 || to == from - 1)
			return getAsso(from, name, to);

		int inc = (to > from) ? 1 : -1;
		Set step = getValues(from, name, to - inc);
		if (step.isEmpty())
			return step;
		
		Iterator iter = step.iterator();
		Set res = new TreeSet();
		while (iter.hasNext()) {
			String stepName = (String) iter.next();
			Set temp = getValues(to - inc, stepName, to);
			res.addAll(temp);
		}
		
		return res;
	}
	
	private Set list(int key) {
		if (getSetForKey(key) == null)
			makeSet(key);
		
		return getSetForKey(key);
	}
	
	public void clear() {
		asso = new TreeMap();
		sets = new Set[NB_KEYS];
	}
	
	private void removeChild(int parentKey, String parentName, String childName) {
		Set res = getValues(parentKey, parentName, parentKey + 1);
		res.remove(childName);
		if (res.isEmpty())
			removeItem(parentKey, parentName);
	}
	
	public void removeItem(int key, String name) {
		if (getSetForKey(key) == null || !getSetForKey(key).remove(name))
			return;
		
		if  (isSpecialKey(key))
			/* If we had a reference count : associatedNode.ref-- */
			return;
		
		Set desc = getValues(key, name, key + 1);
		Iterator iter = desc.iterator();
		while (iter.hasNext()) {
			String childName = (String) iter.next();
			removeItem(key + 1, childName);
		}
		
		Set parent = getValues(key, name, key - 1);
		iter = parent.iterator();
		while (iter.hasNext()) {
			String parentName = (String) iter.next();
			removeChild(key - 1, parentName, name);
		}
	}
	
	public void dumpMap() {
		Iterator keys = asso.keySet().iterator();
		while (keys.hasNext()) {
			AssoKey key = (AssoKey) keys.next();
			System.out.println(key);
			Iterator values = ((Set) asso.get(key)).iterator();
			while (values.hasNext()) {
				System.out.println(" " + values.next());
			}
		}
	}
}

@@ -3162,49 +3162,8 @@
 ) %7B%0A
-%09%09System.out.println(from + %22 - %22 + to);%0A
 %09%09if

Remove a too verbose println