//------------------------------------------------------------------------------
// 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.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);
	}

	public static final Comparator 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 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);
		}
	};

	
}
