/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dowser.ui;

import dowser.model.Attribute;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import dowser.model.DomainModel;
import dowser.model.Operation;
import dowser.model.Relation;

/**
 *
 * @author Chetan Pawgi
 */
public class DomainTreeModel implements TreeModel {

	public class Node {

		protected Object m_Data;
		protected String m_Text;
		protected int m_ChildCount;

		public Node(String text, Object data, int childCount) {
			m_Text = text;
			m_Data = data;
			m_ChildCount = childCount;
		}

		public Node(String text, Object data) {
			this(text, data, 0);
		}

		public Node(String text) {
			this(text, null, 0);
		}

		public Object getData() {
			return m_Data;
		}

		public String getText() {
			return m_Text;
		}

		public int getChildCount() {
			return m_ChildCount;
		}
	}
	public static final String RELATIONS_NODE_TEXT = "Relations";
	public static final String CLASSES_NODE_TEXT = "Classes";
	public static final String ATTRIBUTES_NODE_TEXT = "Atrributes";
	public static final String OPERATIONS_NODE_TEXT = "Operations";
	public static final String SUPERCLASSES_NODE_TEXT = "SuperClasses";
	public static final String SUBCLASSES_NODE_TEXT = "SubClasses";
	protected DomainModel m_model;
	protected Set<TreeModelListener> m_Listeners = Collections.synchronizedSet(new HashSet<TreeModelListener>());

	public DomainTreeModel() {
	}

	public void setModel(DomainModel model) {
		m_model = model;
		notifyListeners();
	}

	public void notifyListeners() {
		for (TreeModelListener l : m_Listeners) {
			l.treeStructureChanged(new TreeModelEvent(m_model, new Object[]{m_model}));
		}
	}

	public void addTreeModelListener(TreeModelListener l) {
		m_Listeners.add(l);
	}

	public Object getChild(Object parent, int index) {
		if (index < 0) {
			return null;
		}
		if (parent instanceof DomainModel) {
			if (index == 0) {
				return new Node(CLASSES_NODE_TEXT + " : " + m_model.getClassCount(), m_model, m_model.getClassCount());
			} else {
				return new Node(RELATIONS_NODE_TEXT + " : " + m_model.getRelationCount(), m_model, m_model.getRelationCount());
			}
		} else if (parent instanceof Node) {
			Node node = (Node) parent;
			String str = node.getText();
			if (str.startsWith(CLASSES_NODE_TEXT)) {
				DomainModel model = (DomainModel) node.getData();
				return model.getClass(index);
			} else if (str.startsWith(RELATIONS_NODE_TEXT)) {
				DomainModel model = (DomainModel) node.getData();
				return model.getRelation(index);
			} else if (str.startsWith(ATTRIBUTES_NODE_TEXT)) {
				dowser.model.Class cClass = (dowser.model.Class) node.getData();
				return cClass.getAttribute(index);
			} else if (str.startsWith(OPERATIONS_NODE_TEXT)) {
				dowser.model.Class cClass = (dowser.model.Class) node.getData();
				return cClass.getOperation(index);
			} else if (str.startsWith(SUPERCLASSES_NODE_TEXT)) {
				dowser.model.Class cClass = (dowser.model.Class) node.getData();
				return cClass.getSuperClasses().get(index);
			} else if (str.startsWith(SUBCLASSES_NODE_TEXT)) {
				dowser.model.Class cClass = (dowser.model.Class) node.getData();
				return cClass.getSubClasses().get(index);
			}
		} else if (parent instanceof Relation) {
			Relation r = (Relation) parent;
			return r.getParticipant(index);
		} else if (parent instanceof dowser.model.Class) {
			dowser.model.Class cClass = (dowser.model.Class) parent;
			switch (index) {
				case 0:
					return new Node(ATTRIBUTES_NODE_TEXT + " : " + cClass.getAttributeCount(), cClass, cClass.getAttributeCount());
				case 1:
					return new Node(OPERATIONS_NODE_TEXT + " : " + cClass.getOperationCount(), cClass, cClass.getOperationCount());
				case 2:
					return new Node(SUPERCLASSES_NODE_TEXT + " : " + cClass.getSuperClasses().size(), cClass, cClass.getSuperClasses().size());
				case 3:
					return new Node(SUBCLASSES_NODE_TEXT + " : " + cClass.getSubClasses().size(), cClass, cClass.getSubClasses().size());
			}
		}
		return null;
	}

	public int getChildCount(Object parent) {
		if (parent instanceof DomainModel) {
			return 2;
		} else if (parent instanceof Relation) {
			return ((Relation) parent).getParticipantCount();
		} else if (parent instanceof dowser.model.Class) {
			return 4;
		} else if (parent instanceof Node) {
			return ((Node) parent).getChildCount();
		}
		return 0;
	}

	public int getIndexOfChild(Object parent, Object child) {
		if (parent instanceof DomainModel) {
			Node node = (Node) child;
			if (node.getText().startsWith(CLASSES_NODE_TEXT)) {
				return 0;
			} else {
				return 1;
			}
		} else if (parent instanceof Node) {
			Node node = (Node) parent;
			String str = node.getText();
			if (str.startsWith(CLASSES_NODE_TEXT)) {
				DomainModel model = (DomainModel) node.getData();
				return model.getIndexOfClass((dowser.model.Class) child);
			} else if (str.startsWith(RELATIONS_NODE_TEXT)) {
				DomainModel model = (DomainModel) node.getData();
				return model.getIndexOfRelation((Relation) child);
			} else if (str.startsWith(ATTRIBUTES_NODE_TEXT)) {
				dowser.model.Class cClass = (dowser.model.Class) node.getData();
				return cClass.getIndexOfAttribute((Attribute) child);
			} else if (str.startsWith(OPERATIONS_NODE_TEXT)) {
				dowser.model.Class cClass = (dowser.model.Class) node.getData();
				return cClass.getIndexOfOperation((Operation) child);
			} else if (str.startsWith(SUPERCLASSES_NODE_TEXT)) {
				dowser.model.Class cClass = (dowser.model.Class) node.getData();
				return cClass.getSuperClasses().indexOf(child);
			} else if (str.startsWith(SUBCLASSES_NODE_TEXT)) {
				dowser.model.Class cClass = (dowser.model.Class) node.getData();
				return cClass.getSubClasses().indexOf(child);
			}
		} else if (parent instanceof Relation) {
			Relation r = (Relation) parent;
			return r.getParticipants().indexOf(child);
		} else if (parent instanceof dowser.model.Class) {
			Node node = (Node) child;
			if (node.getText().startsWith(ATTRIBUTES_NODE_TEXT)) {
				return 0;
			}
			if (node.getText().startsWith(OPERATIONS_NODE_TEXT)) {
				return 1;
			}
			if (node.getText().startsWith(SUPERCLASSES_NODE_TEXT)) {
				return 2;
			}
			if (node.getText().startsWith(SUBCLASSES_NODE_TEXT)) {
				return 3;
			}
		}
		return -1;
	}

	public Object getRoot() {
		return m_model;
	}

	public boolean isLeaf(Object node) {
		return getChildCount(node) == 0;
	}

	public void removeTreeModelListener(TreeModelListener l) {
		m_Listeners.remove(l);
	}

	public void valueForPathChanged(TreePath path, Object newValue) {
	}

	public DomainModel getDomainModel() {
		return m_model;
	}
}
