/*******************************************************************************
 * Copyright (c) 2003, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.j2ee.internal.ejb.provider;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationWrapper;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.jst.j2ee.ejb.EJBJar;
import org.eclipse.jst.j2ee.ejb.EjbPackage;
import org.eclipse.jst.j2ee.ejb.EnterpriseBean;
import org.eclipse.jst.j2ee.ejb.Entity;
import org.eclipse.jst.j2ee.ejb.MessageDriven;
import org.eclipse.jst.j2ee.ejb.Session;
import org.eclipse.jst.j2ee.internal.J2EEVersionConstants;
import org.eclipse.jst.j2ee.internal.plugin.J2EEPlugin;
import org.eclipse.jst.j2ee.internal.provider.J2EEItemProvider;


/**
 * @author Sachin P Patel
 * 
 * To change this generated comment edit the template variable "typecomment":
 * Window>Preferences>Java>Templates. To enable and disable the creation of type comments go to
 * Window>Preferences>Java>Code Generation.
 */
public class GroupedEJBJarItemProvider extends EJBJarItemProvider {

	private GroupedSessionItemProvider sessionProvider = null;
	private GroupedEntityItemProvider entityProvider = null;
	private GroupedMessageItemProvider messageProvider = null;

	private static Hashtable sessionTable = new Hashtable();
	private static Hashtable entityTable = new Hashtable();
	private static Hashtable messageTable = new Hashtable();

	private static final String SESSION = EJBUIMessages.GroupedEJBJarItemProvider_UI_0;
	private static final String ENTITY = EJBUIMessages.GroupedEJBJarItemProvider_UI_1;
	private static final String MESSAGE = EJBUIMessages.GroupedEJBJarItemProvider_UI_2;

	//	Normally there is one instance of an item provider for all instances of the objecct
	//	in the tree. The item provider would be stateless. However, because we are doing tricks
	//	here, we are keeping track of all items this provider manages. The key in the map is the
	//	object (EJBJar), and the value is the children nodes that we inserted

	protected Map children = new HashMap();
	private boolean showAssemblyDescriptor;
	private boolean isDisposing;

	public GroupedEJBJarItemProvider(AdapterFactory adapterFactory, boolean showAssemblyDescriptor) {
		super(adapterFactory);
		this.showAssemblyDescriptor = showAssemblyDescriptor;
	}

	@Override
	public Collection getChildren(Object object) {
		List result = initChildren(object);
		if (showAssemblyDescriptor) {
			if (((EJBJar) object).getAssemblyDescriptor() != null)
				result.add(((EJBJar) object).getAssemblyDescriptor());
		}
		return result;
	}

	protected List initChildren(Object object) {
		EJBJar ejbJar = (EJBJar) object;
		List allRootBeans = getAllRootBeans(ejbJar);

		boolean is20Jar = is20Jar(ejbJar);

		List localChildren = new ArrayList(5);

		List entityBeans = new ArrayList();
		List sessionBeans = new ArrayList();
		List messageBeans = new ArrayList();

		catagorizeBeans(allRootBeans, entityBeans, sessionBeans, messageBeans);
		orderBeans(entityBeans);
		orderBeans(sessionBeans);
		orderBeans(messageBeans);
		
		//ENABLE FOR: NOT TO SHOW EMPTY GROUPS
		//if (sessionBeans.size() > 0) {
		if (sessionTable.get(ejbJar) == null) {
			//create new item provider instance
			sessionProvider = new GroupedSessionItemProvider(adapterFactory, null, getImage(SESSION), object, sessionBeans);
			sessionTable.put(ejbJar, sessionProvider);
			localChildren.add(sessionProvider);
		} else {
			//use existing instance from table
			localChildren.add(sessionTable.get(ejbJar));
		}
		//}

		//ENABLE FOR: NOT TO SHOW EMPTY GROUPS
		//if (entityBeans.size() > 0) {
		if (entityTable.get(ejbJar) == null) {
			//create new item provider instance
			entityProvider = new GroupedEntityItemProvider(adapterFactory, null, getImage(ENTITY), object, entityBeans);
			entityTable.put(ejbJar, entityProvider);
			localChildren.add(entityProvider);
		} else {
			//use existing instance from table
			localChildren.add(entityTable.get(ejbJar));
		}
		//}

		//ENABLE FOR: NOT TO SHOW EMPTY GROUPS
		//if (is20Jar && messageBeans.size() > 0) {
		if (is20Jar) {
			if (messageTable.get(ejbJar) == null) {
				//create new item provider instance
				messageProvider = new GroupedMessageItemProvider(adapterFactory, null, getImage(MESSAGE), object, messageBeans);
				messageTable.put(ejbJar, messageProvider);
				localChildren.add(messageProvider);
			} else {
				//use existing instance from table
				localChildren.add(messageTable.get(ejbJar));
			}
		}
		//}

		children.put(object, localChildren);

		return localChildren;
	}

	protected void orderBeans(List beans) {
		Object[] beansArray = beans.toArray();
		Arrays.sort(beansArray, EJBNameComparator.singleton());
		beans.clear();
		beans.addAll(Arrays.asList(beansArray));
	}
	
	protected static List getAllRootBeans(EJBJar ejbJar) {
		return ejbJar.getEnterpriseBeans();
	}

	protected void catagorizeBeans(List allRootBeans, List entityBeans, List sessionBeans, List messageBeans) {
		for (int i = 0; i < allRootBeans.size(); i++) {
			if (((EnterpriseBean) allRootBeans.get(i)).isSession()) {
				sessionBeans.add(allRootBeans.get(i));
			} else if (((EnterpriseBean) allRootBeans.get(i)).isEntity()) {
				entityBeans.add(allRootBeans.get(i));
			} else if (((EnterpriseBean) allRootBeans.get(i)).isMessageDriven()) {
				messageBeans.add(allRootBeans.get(i));
			}
		}
	}

	static protected GroupedSessionItemProvider getSessionNode(Object object) {
		return (GroupedSessionItemProvider) sessionTable.get(object);
	}

	static protected GroupedEntityItemProvider getEntityNode(Object object) {
		return (GroupedEntityItemProvider) entityTable.get(object);
	}

	static protected GroupedMessageItemProvider getMessageNode(Object object) {
		return (GroupedMessageItemProvider) messageTable.get(object);
	}

	@Override
	public Object getImage(String type) {
		if (type.equals(SESSION))
			return J2EEPlugin.getPlugin().getImage("sessionBean_obj"); //$NON-NLS-1$
		else if (type.equals(MESSAGE))
			return J2EEPlugin.getPlugin().getImage("message_bean_obj"); //$NON-NLS-1$
		else if (type.equals(ENTITY))
			return J2EEPlugin.getPlugin().getImage("entitybean_obj"); //$NON-NLS-1$
		else
			return null;
	}

	private boolean is20Jar(EJBJar ejbJar) {
		switch (ejbJar.getVersionID()) {
			case J2EEVersionConstants.EJB_1_0_ID :
			case J2EEVersionConstants.EJB_1_1_ID :
				return false;
			case J2EEVersionConstants.EJB_2_0_ID :
			case J2EEVersionConstants.EJB_2_1_ID :
			default :
				return true;
		}
	}

	@Override
	public void notifyChanged(Notification notification) {
		if (notification.getEventType() == Notification.REMOVING_ADAPTER && notification.getOldValue() == this && !isDisposing) {
			removeTarget(notification);
			return;
		}
		if (notification.getFeature() == EjbPackage.eINSTANCE.getEJBJar_EnterpriseBeans()) {
			J2EEItemProvider provider = beansChanged((EJBJar) notification.getNotifier(), notification.getEventType(), notification.getOldValue(), notification.getNewValue(), notification.getPosition());

			//EJB's group has not been added yet, need to add group to tree before EJB can be added
			if (provider == null) {
				Notification msg = new NotificationImpl(Notification.ADD, null, getEJBItemProvider((EnterpriseBean) notification.getNewValue()), 1);
				NotificationWrapper notificationWrapper = new NotificationWrapper(notification.getNotifier(), msg);
				fireNotifyChanged(notificationWrapper);
				provider = beansChanged((EJBJar) notification.getNotifier(), notification.getEventType(), notification.getOldValue(), notification.getNewValue(), notification.getPosition());
			}

			//Fire notification for EJB add or remove
			NotificationWrapper notificationWrapper = new NotificationWrapper(provider, notification);
			fireNotifyChanged(notificationWrapper);

			//ENABLE FOR: NOT TO SHOW EMPTY GROUPS
			//If Group is empty remove the group
			/*
			 * if (provider != null && provider.getChildren().size() == 0) { Notification msg = new
			 * NotificationImpl(Notification.REMOVE, provider, null, 1); notificationWrapper = new
			 * NotificationWrapper(notification.getNotifier(), msg);
			 * fireNotifyChanged(notificationWrapper);
			 * 
			 * //Group is removed so flush out table entry if (provider instanceof
			 * GroupedSessionItemProvider) { sessionTable.remove(notification.getNotifier());
			 * provider = null; } else if (provider instanceof GroupedEntityItemProvider) {
			 * entityTable.remove(notification.getNotifier()); provider = null; } else if (provider
			 * instanceof GroupedMessageItemProvider) {
			 * messageTable.remove(notification.getNotifier()); provider = null; }
			 * 
			 * //If all groups are removed remove the extended children List allChildren = new
			 * ArrayList(this.getChildren((EJBJar) notification.getNotifier()));
			 * if(sessionTable.get(notification.getNotifier()) == null &&
			 * entityTable.get(notification.getNotifier()) == null &&
			 * messageTable.get(notification.getNotifier()) == null) { for(int i = 0; i <
			 * allChildren.size(); i++) { Notification message = new
			 * NotificationImpl(Notification.REMOVE, allChildren.get(i), null, 1);
			 * notificationWrapper = new NotificationWrapper(notification.getNotifier(), message);
			 * fireNotifyChanged(notificationWrapper); } this.getChildren((EJBJar)
			 * notification.getNotifier()).clear(); } }
			 */
		} else {
			super.notifyChanged(notification);
		}
	}

	protected J2EEItemProvider beansChanged(EJBJar ejbJar, int eventType, Object oldValue, Object newValue, int pos) {
		J2EEItemProvider provider = getItemProvider(ejbJar, oldValue, newValue);

		if (provider != null) {
			Collection grandChildren = provider.getChildren();

			switch (eventType) {
				case Notification.ADD : {
					if (!grandChildren.contains(newValue))
						grandChildren.add(newValue);

					break;
				}
				case Notification.ADD_MANY : {
					grandChildren.addAll((Collection) newValue);
					break;
				}
				case Notification.REMOVE : {
					grandChildren.remove(oldValue);
					break;
				}
				case Notification.REMOVE_MANY : {
					grandChildren.removeAll((Collection) oldValue);
					break;
				}
			}
		} else {
			//GroupedProvider for new bean does not exist, create one.
			List allRootBeans = getAllRootBeans(ejbJar);

			List entityBeans = new ArrayList();
			List sessionBeans = new ArrayList();
			List messageBeans = new ArrayList();

			catagorizeBeans(allRootBeans, entityBeans, sessionBeans, messageBeans);

			if (newValue instanceof Session) {
				sessionProvider = new GroupedSessionItemProvider(adapterFactory, null, getImage(SESSION), ejbJar, sessionBeans);
				sessionTable.put(ejbJar, sessionProvider);
			} else if (newValue instanceof Entity) {
				entityProvider = new GroupedEntityItemProvider(adapterFactory, null, getImage(ENTITY), ejbJar, entityBeans);
				entityTable.put(ejbJar, entityProvider);
			} else if (newValue instanceof MessageDriven) {
				messageProvider = new GroupedMessageItemProvider(adapterFactory, null, getImage(MESSAGE), ejbJar, messageBeans);
				messageTable.put(ejbJar, messageProvider);
			}
		}
		return provider;
	}

	static public J2EEItemProvider getEJBJarItemProvider(EJBJar ejbJar, Object bean) {
		J2EEItemProvider provider = null;
		if (ejbJar != null && bean != null) {
			if (bean instanceof Session) {
				provider = getSessionNode(ejbJar);
			} else if (bean instanceof Entity) {
				provider = getEntityNode(ejbJar);
			} else if (bean instanceof MessageDriven) {
				provider = getMessageNode(ejbJar);
			}
		}
		return provider;
	}

	static public J2EEItemProvider getEJBItemProvider(EnterpriseBean bean) {
		if (bean != null) {
			EJBJar ejbJar = bean.getEjbJar();
			return getEJBJarItemProvider(ejbJar, bean);
		}
		return null;
	}

	protected J2EEItemProvider getItemProvider(EJBJar ejbJar, Object oldValue, Object newValue) {
		if (newValue != null)
			return getEJBJarItemProvider(ejbJar, newValue);
		else if (oldValue != null)
			return getEJBJarItemProvider(ejbJar, oldValue);
		else
			return null;
	}

	public static boolean isRootBean(EnterpriseBean bean) {
		List allRootBeans = getAllRootBeans(bean.getEjbJar());
		if (allRootBeans != null && allRootBeans.contains(bean)) {
			return true;
		}
		return false;
	}

	//	Utility method for garbage collection - if EJBJar removed, remove
	//	all entires in table for EJBJar
	static public void flushOutTableEntriesForEJBJar(EJBJar ejbJar) {
		sessionTable.remove(ejbJar);
		entityTable.remove(ejbJar);
		messageTable.remove(ejbJar);
	}

	@Override
	public boolean hasChildren(Object parent) {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.j2ee.internal.internal.ejb.provider.EJBJarItemProvider#removeTarget(org.eclipse.emf.common.notify.Notification)
	 */
	protected void removeTarget(Notification not) {
		if (not.getNotifier() instanceof EJBJar)
			flushOutTableEntriesForEJBJar((EJBJar) not.getNotifier());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.edit.provider.ItemProviderAdapter#dispose()
	 */
	@Override
	public void dispose() {
		try {
			isDisposing = true;
			super.dispose();
		} finally {
			isDisposing = false;
		}
	}
}
