//------------------------------------------------------------------------------
// 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.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.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.ContentElement;
import org.eclipse.epf.uma.Section;
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.ContentDescriptionFactory;
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 Phong Nguyen Le
 * @since 1.0
 */
public class SectionList extends BasicEList {

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

	private static final String ORDER_INFO_NAME = "sections"; //$NON-NLS-1$

	private static final Map DEFAULT_SAVE_OPTIONS = new HashMap();

	public static final int STEPS_FOR_ELEMENT_ONLY = 1;

	public static final int STEPS_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 static boolean isContributor(VariabilityElement e) {
		return TngUtil.isContributor(e);
	}

	public SectionList(ContentElement e, int scope) {
		editElement = e;
		if (scope == STEPS_FOR_ELEMENT_ONLY) {
			mixed = false;
		} else if (scope == STEPS_FOR_ELEMENT_AND_PARENTS) {
			calculateParentsOnly(e);
		} else {
			mixed = false;
		}
	}

	private void calculateParentsOnly(ContentElement e) {
		Iterator iter = null;
		// if(isContributor(e)) {
		// // System.out.println("$$$ for " + e.getName() + " = contributing is
		// true");
		// List supers = new ArrayList();
		// UmaUtil.getAllSupers(supers, e, VariabilityType.CONTRIBUTES_LITERAL);
		// supers.add(e);
		// iter = supers.iterator();
		// } else if(isExtended(e)) {
		// // System.out.println("$$$ for " + e.getName() + " = extending is
		// true");
		// List supers = new ArrayList();
		// UmaUtil.getAllSupers(supers, e, VariabilityType.EXTENDS_LITERAL);
		// supers.add(e);
		// iter = supers.iterator();
		// }
		if (isContributor(e) || isExtended(e)) {
			// System.out.println("$$$ for " + e.getName() + " = contributing is
			// true");
			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 guidSectionMap = new HashMap();
			Set sects = new LinkedHashSet();
			while (iter.hasNext()) {
				ContentElement element = (ContentElement) iter.next();
				if (ContentDescriptionFactory.hasPresentation(element)) {
					for (Iterator iterator = element.getPresentation()
							.getSections().iterator(); iterator.hasNext();) {
						Section sect = (Section) iterator.next();
						guidSectionMap.put(sect.getGuid(), sect);
						sects.add(sect);
					}
				}
				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 sect = guidSectionMap.get(guid);
					if (sect != null) {
						super.add(sect);
						sects.remove(sect);
					}
				}
			}
			super.addAll(sects);
		}
	}

	// deprecate the following constructor
	public SectionList(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 guidSectionMap = new HashMap();
			List sects = new LinkedList();
			while (iter.hasNext()) {
				ContentElement element = (ContentElement) iter.next();
				if (ContentDescriptionFactory.hasPresentation(element)) {
					for (Iterator iterator = element.getPresentation()
							.getSections().iterator(); iterator.hasNext();) {
						Section sect = (Section) iterator.next();
						guidSectionMap.put(sect.getGuid(), sect);
						sects.add(sect);
					}
				}
				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 sect = guidSectionMap.get(guid);
					if (sect != null) {
						super.add(sect);
						sects.remove(sect);
					}
				}
			}
			super.addAll(sects);
		}
		// 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++) {
			Section sect = (Section) 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(Section section) {
		if (ContentDescriptionFactory.hasPresentation(editElement)) {
			return editElement.getPresentation() == section.eContainer();
		}
		return false;
	}

	public Object remove(int index) {
		if (mixed) {
			if (!canRemove((Section) get(index)))
				return null;
			Object removed = super.remove(index);
			editElement.getPresentation().getSections().remove(removed);
			return removed;
		} else {
			return editElement.getPresentation().getSections().remove(index);
		}
	}

	public boolean remove(Object o) {
		if (!canRemove((Section) o))
			return false;
		if (mixed) {
			if (super.remove(o)) {
				editElement.getPresentation().getSections().remove(o);
				return true;
			}
			return false;
		}
		return editElement.getPresentation().getSections().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((Section) o)) {
					e.remove();
					editElement.getPresentation().getSections().remove(o);
					modified = true;
				}
			}
			return modified;
		} else {
			return editElement.getPresentation().getSections().removeAll(c);
		}
	}

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

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

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

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

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

	public void clear() {
		if (mixed)
			throw new UnsupportedOperationException();
		editElement.getPresentation().getSections().clear();
	}

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

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

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

	public int size() {
		if (mixed) {
			return super.size();
		} else {
			return editElement.getPresentation().getSections().size();
		}
	}

	public Iterator iterator() {
		if (mixed) {
			return super.iterator();
		} else {
			return editElement.getPresentation().getSections().iterator();
		}
	}

	public boolean contains(Object object) {
		if (mixed) {
			return super.contains(object);
		}
		return editElement.getPresentation().getSections().contains(object);
	}

	public boolean containsAll(Collection collection) {
		if (mixed)
			return super.containsAll(collection);
		return editElement.getPresentation().getSections().containsAll(
				collection);
	}

	public Object[] toArray() {
		if (mixed) {
			return super.toArray();
		}
		return editElement.getPresentation().getSections().toArray();
	}

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

	public int indexOf(Object object) {
		if (mixed)
			return super.indexOf(object);
		return editElement.getPresentation().getSections().indexOf(object);
	}

	public int lastIndexOf(Object object) {
		if (mixed)
			return super.lastIndexOf(object);
		return editElement.getPresentation().getSections().lastIndexOf(object);
	}

	public boolean isMixed() {
		return mixed;
	}
}
