//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006, 2007 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.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.epf.library.edit.util.model.ModelFactory;
import org.eclipse.epf.library.edit.util.model.OrderInfo;
import org.eclipse.epf.library.edit.util.model.OrderInfoCollection;
import org.eclipse.epf.library.edit.util.model.util.StringResource;
import org.eclipse.epf.uma.ContentCategory;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.util.AssociationHelper;
import org.eclipse.epf.uma.util.UmaUtil;

/**
 * 
 * This class encapsulates all the logics used to retrieve the list of all
 * contributed/inherited sections of the given element as well as allows
 * manipulate this list.
 * 
 * @author Lokanath Jagga
 * @author Phong Nguyen Le
 * @since 1.0
 */
public class ContentElementOrderList extends BasicEList {

	/**
	 * 
	 */
	private static final long serialVersionUID = 3257572797487069233L;

	public static final String ORDER_INFO_NAME = "content elements"; //$NON-NLS-1$

	private static final Map DEFAULT_SAVE_OPTIONS = new HashMap();

	public static final int CONTENT_ELEMENTS__FOR_ELEMENT_ONLY = 1;

	public static final int CONTENT_ELEMENTS__FOR_ELEMENT_AND_PARENTS = 2;

	static {
		DEFAULT_SAVE_OPTIONS.put(XMLResource.OPTION_ENCODING, "ASCII"); //$NON-NLS-1$
	}

	private ContentElement editElement;

	private boolean mixed = true;

	private boolean changed = false;

	private EStructuralFeature feature;

	private static boolean isContributor(VariabilityElement e) {
		return TngUtil.isContributor(e);
	}

	public ContentElementOrderList(ContentElement e, int scope, EStructuralFeature feature) {
		this.feature = feature;
		editElement = e;
		if (scope == CONTENT_ELEMENTS__FOR_ELEMENT_ONLY) {
			mixed = false;
		} else if (scope == CONTENT_ELEMENTS__FOR_ELEMENT_AND_PARENTS) {
			calculateParentsOnly(e);
		} else {
			mixed = false;
		}
	}

	private void calculateParentsOnly(ContentElement e) {
		Iterator iter = null;
		if (isContributor(e) || isExtended(e)) {
			List supers = new ArrayList();
			UmaUtil.getAllSupersBoth(supers, e,
					VariabilityType.CONTRIBUTES,
					VariabilityType.EXTENDS);
			supers.add(e);
			iter = supers.iterator();
		} else {
			mixed = false;
		}

		if (mixed) {
			// create a map of GUID / contributor 
			
			OrderInfo latestInfo = null;
			Map guidMap = new HashMap();
			Set elements = new LinkedHashSet();
			while (iter.hasNext()) {
				ContentElement element = (ContentElement) iter.next();
				if (element instanceof ContentElement) {
					List contentElements = new ArrayList();
					Object eGet = ((ContentElement) element).eGet(feature);
					if (eGet instanceof List) {
						contentElements.addAll((List) eGet);
					}
					for (Iterator iterator = contentElements.iterator(); iterator
							.hasNext();) {
						DescribableElement categorizedElement = (DescribableElement) iterator
								.next();
						guidMap.put(categorizedElement.getGuid(),
								categorizedElement);
						elements.add(categorizedElement);
					}
				}

				OrderInfo orderInfo = TngUtil.getOrderInfo(element,
						ORDER_INFO_NAME);
				if (orderInfo != null) {
					if (latestInfo == null
							|| orderInfo.getTimestamp() > latestInfo
									.getTimestamp()) {
						latestInfo = orderInfo;
					}
				}
			}

			if (latestInfo != null) {
				// reorder the sections based on the latest order info
				int size = latestInfo.getGUIDs().size();
				for (int i = 0; i < size; i++) {
					Object guid = latestInfo.getGUIDs().get(i);
					Object element = guidMap.get(guid);
					if (element != null) {
						super.add(element);
						elements.remove(element);
					}
				}
			}
			super.addAll(elements);
		}
	}

	// deprecate the following constructor
	public ContentElementOrderList(ContentElement e) {
		editElement = e;
		Iterator iter = null;
		if (isContributor(e) || TngUtil.hasContributor(e)) {
			VariabilityElement base = TngUtil.getBase(e);
			iter = new AbstractTreeIterator(base) {

				protected Iterator getChildren(Object object) {
					List children = new ArrayList();
					for (Iterator iterator = AssociationHelper
							.getImmediateVarieties((VariabilityElement) object)
							.iterator(); iterator.hasNext();) {
						VariabilityElement element = (VariabilityElement) iterator
								.next();
						if (element.getVariabilityType() == VariabilityType.CONTRIBUTES) {
							children.add(element);
						}
					}
					return children.iterator();
				}

			};
		} else if (isExtended(e)) {
			System.out
					.println("$$$ for " + e.getName() + " = extended is true"); //$NON-NLS-1$ //$NON-NLS-2$
			List supers = new ArrayList();
			UmaUtil.getAllSupers(supers, e, VariabilityType.EXTENDS);
			supers.add(e);
			iter = supers.iterator();
		} else {
			mixed = false;
		}

		if (mixed) {
			// create a map of GUID / contributor
			OrderInfo latestInfo = null;
			Map guidMap = new HashMap();
			List elements = new LinkedList();
			while (iter.hasNext()) {
				ContentElement element = (ContentElement) iter.next();
				guidMap.put(element.getGuid(), element);
				elements.add(element);

				OrderInfo orderInfo = TngUtil.getOrderInfo(element,
						ORDER_INFO_NAME);
				if (orderInfo != null) {
					if (latestInfo == null
							|| orderInfo.getTimestamp() > latestInfo
									.getTimestamp()) {
						latestInfo = orderInfo;
					}
				}
			}

			if (latestInfo != null) {
				// reorder the sections based on the latest order info
				//
				int size = latestInfo.getGUIDs().size();
				for (int i = 0; i < size; i++) {
					Object guid = latestInfo.getGUIDs().get(i);
					Object element = guidMap.get(guid);
					if (element != null) {
						super.add(element);
						elements.remove(element);
					}
				}
			}
			super.addAll(elements);
		}
		// else {
		// // addAll(editElement.getPresentation().getSections());
		// mixed = false;
		// }
	}

	private static boolean isExtended(ContentElement e) {
		return e.getVariabilityBasedOnElement() != null
				&& e.getVariabilityType() == VariabilityType.EXTENDS;
	}

	/**
	 * Applies recent changes in the list
	 * 
	 */
	public void apply() {
		if (!mixed || !changed)
			return;

		// save the order info to the orderingGuide of the editElement
		//
		String str = editElement.getOrderingGuide();
		OrderInfoCollection orderInfos = null;
		StringResource res = null;
		if (str == null || str.length() == 0) {
			orderInfos = ModelFactory.eINSTANCE.createOrderInfoCollection();
		} else {
			res = new StringResource(str);
			try {
				res.load(null);
				if (res.getContents().isEmpty()) {
					orderInfos = ModelFactory.eINSTANCE
							.createOrderInfoCollection();
				} else {
					orderInfos = (OrderInfoCollection) res.getContents().get(0);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		// find the order infor for sections
		//
		OrderInfo sectOrderInfo = null;
		for (Iterator iter = orderInfos.getOrderInfos().iterator(); iter
				.hasNext();) {
			OrderInfo orderInfo = (OrderInfo) iter.next();
			if (ORDER_INFO_NAME.equalsIgnoreCase(orderInfo.getName())) {
				sectOrderInfo = orderInfo;
				break;
			}
		}

		if (sectOrderInfo == null) {
			sectOrderInfo = ModelFactory.eINSTANCE.createOrderInfo();
			sectOrderInfo.setName(ORDER_INFO_NAME);
			orderInfos.getOrderInfos().add(sectOrderInfo);
		} else {
			sectOrderInfo.getGUIDs().clear();
		}

		int size = size();
		for (int i = 0; i < size; i++) {
			DescribableElement sect = (DescribableElement) get(i);
			sectOrderInfo.getGUIDs().add(sect.getGuid());
		}
		sectOrderInfo.setTimestamp(System.currentTimeMillis());
		if (res == null) {
			res = new StringResource(null);
			res.getContents().add(orderInfos);
		}
		try {
			res.save(DEFAULT_SAVE_OPTIONS);
			str = res.getString();
			// System.out.println("SectionList.apply(): new ordering guide");
			// System.out.println("------ orderingGuide start ------");
			// System.out.println(str);
			// System.out.println("------ orderingGuide end ------");
			editElement.setOrderingGuide(str);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
	}

	public boolean canRemove(ContentElement contentElement) {
		if (eGet().contains(contentElement)) {
			return true;
		}
		return false;
	}

	public Object remove(int index) {
		if (mixed) {
			if (!canRemove((ContentElement) get(index)))
				return null;
			Object removed = super.remove(index);
			eGet().remove(removed);
			return removed;
		} else {
			return eGet().remove(index);
		}
	}

	public boolean remove(Object o) {
		if (!canRemove((ContentElement) o))
			return false;
		if (mixed) {
			if (super.remove(o)) {
				eGet().remove(o);
				return true;
			}
			return false;
		}
		return eGet().remove(o);
	}

	public boolean removeAll(Collection c) {
		if (mixed) {
			boolean modified = false;
			Iterator e = iterator();
			while (e.hasNext()) {
				Object o = e.next();
				if (c.contains(o) && canRemove((ContentElement) o)) {
					e.remove();
					eGet().remove(o);
					modified = true;
				}
			}
			return modified;
		} else {
			return eGet().removeAll(c);
		}
	}

	public void add(int index, Object element) {
		if (mixed) {
			super.add(index, element);
			eGet().add(element);
			changed = true;
		} else {
			eGet().add(index, element);
		}
	}

	public boolean add(Object o) {
		boolean b = eGet().add(o);
		if (mixed) {
			b = super.add(o);
			if (b)
				changed = true;
		}
		return b;
	}

	public boolean addAll(Collection c) {
		boolean b = eGet().addAll(c);
		;
		if (mixed) {
			b = super.addAll(c);
			if (b)
				changed = true;
		}
		return b;
	}

	public boolean addAll(int index, Collection c) {
		if (mixed) {
			eGet().addAll(c);
			;
			boolean b = super.addAll(index, c);
			if (b)
				changed = true;
		}
		return eGet().addAll(c);
	}

	public Object set(int index, Object element) {
		if (mixed)
			throw new UnsupportedOperationException();
		return eGet().set(index, element);
	}

	public void clear() {
		if (mixed)
			throw new UnsupportedOperationException();
		eGet().clear();
	}

	public void move(int index, Object object) {
		if (mixed) {
			super.move(index, object);
			changed = true;
		} else {
			((EList) eGet()).move(index, object);
		}
	}

	public Object move(int targetIndex, int sourceIndex) {
		if (mixed) {
			Object moved = super.move(targetIndex, sourceIndex);
			changed = true;
			return moved;
		} else {
			return eGet().move(targetIndex, sourceIndex);
		}
	}

	public Object get(int index) {
		if (mixed) {
			return super.get(index);
		} else {
			return eGet().get(index);
		}
	}

	public int size() {
		if (mixed) {
			return super.size();
		} else {
			return eGet().size();
		}
	}

	public Iterator iterator() {
		if (mixed) {
			return super.iterator();
		} else {
			return eGet().iterator();
		}
	}

	public boolean contains(Object object) {
		if (mixed) {
			return super.contains(object);
		}
		return eGet().contains(object);
	}

	public boolean containsAll(Collection collection) {
		if (mixed)
			return super.containsAll(collection);
		return eGet().containsAll(collection);
	}

	public Object[] toArray() {
		if (mixed) {
			return super.toArray();
		}
		return eGet().toArray();
	}

	public Object[] toArray(Object[] array) {
		if (mixed)
			return super.toArray(array);
		return eGet().toArray(array);
	}

	public int indexOf(Object object) {
		if (mixed)
			return super.indexOf(object);
		return eGet().indexOf(object);
	}

	public int lastIndexOf(Object object) {
		if (mixed)
			return super.lastIndexOf(object);
		return eGet().lastIndexOf(object);
	}

	public boolean isMixed() {
		return mixed;
	}

	private EList eGet() {
		EList list = null;
		Object object = ((ContentCategory) editElement).eGet(feature);
		if (object instanceof EList) {
			list = (EList) object;
		}
		if (list == null) {
			list = new BasicEList();
		}
		return list;
	}
}
