//------------------------------------------------------------------------------
// 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_LITERAL,
					VariabilityType.EXTENDS_LITERAL);
			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_LITERAL) {
							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_LITERAL);
			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_LITERAL;
	}

	/**
	 * 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;
	}
}
