//------------------------------------------------------------------------------
// 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.services;
import java.util.Collection;
import java.util.Iterator;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.epf.library.ILibraryManager;
import org.eclipse.epf.library.ILibraryServiceListener;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.events.ILibraryChangeListener;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;

import com.ibm.icu.util.Calendar;

/**
 * This class manages the versioning of the element in the method element. 
 * This class is not used any more since version is not managed automatically
 * 
 * @author Jinhua Xi
 * @since 1.0
 * 
 * @deprecated
 */
public class VersionManager {

	private ILibraryManager manager;

	private ILibraryServiceListener libSvcListener = null;
	private ILibraryChangeListener libListener = null;

	private boolean inProcessing = false;

	public VersionManager(ILibraryManager manager) {
		this.manager = manager;
		initialize();
	}

	private void initialize() {
		libSvcListener = new ILibraryServiceListener() {

			public void configurationSet(MethodConfiguration config) {
				//System.out.println("configuration set: " + LibraryUtil.getTypeName(config));
			}

			public void libraryClosed(MethodLibrary library) {
				//System.out.println("Library closed: " + LibraryUtil.getTypeName(library));
			}

			public void libraryCreated(MethodLibrary library) {
				//System.out.println("Library closed: " + LibraryUtil.getTypeName(library));
			}

			public void libraryOpened(MethodLibrary library) {
				//System.out.println("Library opened: " + LibraryUtil.getTypeName(library));
			}

			public void libraryReopened(MethodLibrary library) {
				//System.out.println("Library reopened: " + LibraryUtil.getTypeName(library));
			}

			public void librarySet(MethodLibrary library) {
				//System.out.println("Library set: " + LibraryUtil.getTypeName(library));
			}
			
		};
		LibraryService.getInstance().addListener(libSvcListener);
		
		// add library change listener
		libListener = new ILibraryChangeListener() {
			public void libraryChanged(int option, Collection changedItems) {
				if (option == ILibraryChangeListener.OPTION_CHANGED
					//	|| option == ILibraryChangeListener.OPTION_CREATED
						|| option == ILibraryChangeListener.OPTION_DELETED) {
					if (!inProcessing && changedItems != null) {
						inProcessing = true;
						try {
							processChanges(option, changedItems);
						} finally {
							inProcessing = false;
						}
					}
				}
			}
		};

		manager.addListener(libListener);
	}

	public void dispose() {
		LibraryService.getInstance().removeListener(libSvcListener);

		ILibraryManager manager = (ILibraryManager) LibraryService
				.getInstance().getCurrentLibraryManager();
		if (manager != null) {
			manager.removeListener(libListener);
		}
	}

	private void processChanges(int option, Collection changedItems) {
		// System.out.println("================= BEGIN: processChanges
		// ================");
		// System.out.println("changed items: " + changedItems);
		// System.out.println("================= END: processChanges
		// ================");

		if (changedItems == null || changedItems.size() == 0) {
			return;
		}

		for (Iterator it = changedItems.iterator(); it.hasNext();) {
			MethodElement element = (MethodElement) it.next();
			org.eclipse.epf.uma.MethodUnit pkg;

			// note only package has version,
			// it the changed element is a package
			if (element instanceof org.eclipse.epf.uma.MethodUnit) {
				pkg = (org.eclipse.epf.uma.MethodUnit) element;
				switch (option) {
				case ILibraryChangeListener.OPTION_CHANGED:
					updateVersion(pkg);
					break;

				case ILibraryChangeListener.OPTION_NEWCHILD:
					updateVersion(pkg);
					updateVersion((org.eclipse.epf.uma.MethodUnit) pkg
							.eContainer());
					break;

				case ILibraryChangeListener.OPTION_DELETED:
					updateVersion((org.eclipse.epf.uma.MethodUnit) pkg
							.eContainer());
					break;
				}
			} else if (element != null) // TODO: changedItems somtimes contains
			// null element. This must not be the
			// case.
			{
				// it the element is not a package, update the parent
				EObject parent = element.eContainer();
				while (parent != null
						&& !(parent instanceof org.eclipse.epf.uma.MethodUnit)) {
					parent = parent.eContainer();
				}

				if (parent != null) {
					pkg = (org.eclipse.epf.uma.MethodUnit) parent;
					updateVersion(pkg);
				}

				/*
				 * switch (option) { case ILibraryChangeListener.OPTION_CHANGED:
				 * case ILibraryChangeListener.OPTION_CREATED: case
				 * ILibraryChangeListener.OPTION_DELETED: updateVersion(pkg);
				 * break; }
				 */
			}
		}
	}

	public void updateVersion(org.eclipse.epf.uma.MethodUnit pkg) {
		if (pkg == null) {
			return;
		}

		// String oldVer = pkg.getVersion();

		// create a version number based on the date
		Calendar c = Calendar.getInstance();
		int y = c.get(Calendar.YEAR);
		int m = c.get(Calendar.MONTH) + 1;
		int d = c.get(Calendar.DATE);
		long t = c.getTimeInMillis();

		String baseVer = Integer.toString(y) + Integer.toString(m)
				+ Integer.toString(d);
		String miniVer = Long.toHexString(t);

		boolean oldNotify = pkg.eDeliver();
		try {
			pkg.eSetDeliver(false);
			/*
			 * System.out.println("=============================");
			 * System.out.println(" eDeviler()=" + pkg.eDeliver());
			 * System.out.println("=============================");
			 */
			pkg.setVersion(baseVer + "." + miniVer); //$NON-NLS-1$
		} finally {
			pkg.eSetDeliver(oldNotify);
		}
	}

}
