//------------------------------------------------------------------------------
// Copyright (c) 2005, 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library.edit.util;

import java.util.Comparator;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.epf.library.edit.PresentationContext;
import org.eclipse.epf.library.edit.navigator.PluginUIPackagesItemProvider;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.UmaPackage;

import com.ibm.icu.text.Collator;


/**
 * Collection of comparators
 * 
 * @author Phong Nguyen Le
 * @since 1.0
 */
public final class Comparators {

	public static final Comparator<Object> DEFAULT_COMPARATOR = new Comparator<Object>() {

		public int compare(Object o1, Object o2) {
			if (o1 == o2)
				return 0;
			Collator collator = Collator.getInstance();
			if (o1 instanceof MethodElement && o2 instanceof MethodElement) {
				return collator.compare(((MethodElement) o1).getName(), ((MethodElement) o2).getName());
			}
			Object o1unwrap = TngUtil.unwrap(o1);
			Object o2unwrap = TngUtil.unwrap(o2);
			if (o1unwrap instanceof MethodElement
					&& o2unwrap instanceof MethodElement) {
				return collator.compare(((MethodElement) o1unwrap).getName(), ((MethodElement) o2unwrap).getName());
			}
			return 0;
		}

	};
	
	public static final Comparator<Object> REVERSE_DEFAULT_COMPARATOR = new Comparator<Object>() {

		public int compare(Object o1, Object o2) {
			if (o1 == o2)
				return 0;
			Collator collator = Collator.getInstance();
			if (o1 instanceof MethodElement && o2 instanceof MethodElement) {
				return oppositeValue(collator.compare(((MethodElement) o1).getName(), ((MethodElement) o2).getName()));
			}
			Object o1unwrap = TngUtil.unwrap(o1);
			Object o2unwrap = TngUtil.unwrap(o2);
			if (o1unwrap instanceof MethodElement
					&& o2unwrap instanceof MethodElement) {
				return oppositeValue(collator.compare(((MethodElement) o1unwrap).getName(), ((MethodElement) o2unwrap).getName()));
			}
			return 0;
		}

	};
	
	private static int oppositeValue(int val) {
		if (val != 0) {
			val = 0 - val;
		}
		return val;
	}


	public static abstract class TypeComparator implements Comparator {
		protected Comparator<Object> getDefaultComparator() {
			return DEFAULT_COMPARATOR;
		}
		
		protected abstract int getOrderId(Object obj);

		public int compare(Object o1, Object o2) {
			o1 = TngUtil.unwrap(o1);
			o2 = TngUtil.unwrap(o2);
			if (o1 == o2)
				return 0;
			int ret = 0;
			ret = getOrderId((EObject) o1) - getOrderId((EObject) o2);
			if (ret == 0) {
				return getDefaultComparator().compare(o1, o2);
			}
			return ret;
		}

	}

	private static int comparePresentationName(DescribableElement e1, DescribableElement e2) {
		Collator collator = Collator.getInstance();
		String name1 = e1 instanceof BreakdownElement ? ProcessUtil.getPresentationName((BreakdownElement)e1)
				: e1.getPresentationName();
		if (name1.length() < 1) name1 = e1.getName();
		String name2 = e2 instanceof BreakdownElement ? ProcessUtil.getPresentationName((BreakdownElement)e2)
				: e2.getPresentationName();
		if (name2.length() < 1) name2 = e2.getName();
		return collator.compare(name1, name2);
	}
	
	private static DescribableElement getDescribableElement(Object obj) {
		Object object = TngUtil.unwrap(obj);
		if (object instanceof ProcessComponent)
			object = ((ProcessComponent) object).getProcess();
		object = TngUtil.unwrap(object);
		if(object instanceof DescribableElement) {
			return (DescribableElement)object;
		}
		return null;
	}

	public static final Comparator PRESENTATION_NAME_COMPARATOR = new Comparator() {
		
		public int compare(Object o1, Object o2) {
			if (o1 == o2)
				return 0;
			o1 = getDescribableElement(o1);
			if (o1 == null) {
				return 0;
			}

			o2 = getDescribableElement(o2);
			if (o2 == null) {
				return 0;
			}

			return comparePresentationName((DescribableElement) o1, (DescribableElement) o2);
		}

	};
	
	public static final Comparator REVERSE_PRESENTATION_NAME_COMPARATOR = new Comparator() {
		
		public int compare(Object o1, Object o2) {
			if (o1 == o2)
				return 0;
			if(!(o1 instanceof DescribableElement)) {
				o1 = TngUtil.unwrap(o1);
				if(!(o1 instanceof DescribableElement)) {
					return 0;
				}
			}
			if(!(o2 instanceof DescribableElement)) {
				o2 = TngUtil.unwrap(o2);
				if(!(o2 instanceof DescribableElement)) {
					return 0;
				}
			}
			return oppositeValue(comparePresentationName((DescribableElement) o1, (DescribableElement) o2));
		}

	};

	public static final Comparator METHOD_TYPE_COMPARATOR = new TypeComparator() {
		/* (non-Javadoc)
		 * @see org.eclipse.epf.library.edit.util.Comparators.TypeComparator#getDefaultComparator()
		 */
		protected Comparator getDefaultComparator() {
			return PresentationContext.INSTANCE.getComparator();
		}

		protected int getOrderId(Object obj) {
			if (obj instanceof MethodElement) {
				int id = ((MethodElement) obj).eClass().getClassifierID();
				if (id == UmaPackage.TERM_DEFINITION) {
					id = Integer.MAX_VALUE;
				}
				return id;
			}
			return -1;
		}
	};
	
	/**
	 * Always sort by presentation name
	 */
	public static final Comparator METHOD_TYPE_PRES_NAME_COMPARATOR = new TypeComparator() {
		/* (non-Javadoc)
		 * @see org.eclipse.epf.library.edit.util.Comparators.TypeComparator#getDefaultComparator()
		 */
		protected Comparator getDefaultComparator() {
			return PresentationContext.INSTANCE.getPresNameComparator();
		}

		protected int getOrderId(Object obj) {
			if (obj instanceof MethodElement) {
				int id = ((MethodElement) obj).eClass().getClassifierID();
				if (id == UmaPackage.TERM_DEFINITION) {
					id = Integer.MAX_VALUE;
				}
				return id;
			}
			return -1;
		}
	};

	public static final Comparator PLUGINPACKAGE_COMPARATOR = new Comparator() {
	
		public int compare(Object o1, Object o2) {
			if (o1 == o2)
				return 0;
			o1 = TngUtil.unwrap(o1);
			o2 = TngUtil.unwrap(o2);
			
			
			if (o1 instanceof PluginUIPackagesItemProvider && o2 instanceof MethodPlugin) {
				return -1;
			}
			if (o1 instanceof MethodPlugin && o2 instanceof PluginUIPackagesItemProvider) {
				return 1;
			}
	
			boolean usePresName = PresentationContext.INSTANCE.isShowPresentationNames();
			String s1 = null;
			String s2 = null;
			if (usePresName && o1 instanceof DescribableElement) {
				s1 = ((DescribableElement) o1).getPresentationName();
			} else if (o1 instanceof MethodElement) {
				s1 = ((MethodElement) o1).getName();
			} else if (o1 instanceof PluginUIPackagesItemProvider) {
				s1 = ((PluginUIPackagesItemProvider) o1).getFullName();
			} else if (o1 instanceof String) {
				s1 = (String) o1;
			} 
			
			if (usePresName && o2 instanceof DescribableElement) {
				s2 = ((DescribableElement) o2).getPresentationName();
			} else if (o2 instanceof MethodElement) {
				s2 = ((MethodElement) o2).getName();
			} else if (o2 instanceof PluginUIPackagesItemProvider) {
				s2 = ((PluginUIPackagesItemProvider) o2).getFullName();
			} else if (o2 instanceof String) {
				s2 = (String) o2;
			}
			
			if (s1 == null || s2 == null) {
				return 0;
			}
			
			return s1.compareToIgnoreCase(s2);
		}
	};

	
}
