//------------------------------------------------------------------------------
// 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.authoring.gef.viewer;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.epf.diagram.model.util.GraphicalDataHelper;
import org.eclipse.epf.diagram.model.util.GraphicalDataManager;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.VariabilityInfo;
import org.eclipse.epf.library.edit.util.Suppression;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.layout.ProcessAdapterFactoryFilter;
import org.eclipse.epf.library.layout.diagram.DiagramInfo;
import org.eclipse.epf.library.layout.diagram.IActivityDiagramService;
import org.eclipse.epf.library.services.SafeUpdateController;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;


/**
 * Provides service methods for creating diagram images for activity elements
 * 
 * @author Jinhua Xi
 * @since 1.0
 */
public class ActivityDiagramService implements IActivityDiagramService {

	private Composite parent = null;

	private Composite holder = null;

	private File pubDir;

	private static Map typeMap = new HashMap();

	private DiagramInfo diagramInfo = null;

	private boolean publishUncreatedADD = true;
	
	private boolean publishADForActivityExtension = true;

	static {
		typeMap.put(ResourceHelper.DIAGRAM_TYPE_WORKFLOW, new Integer(
				GraphicalDataHelper.ACTIVITY_DIAGRAM));
		typeMap.put(ResourceHelper.DIAGRAM_TYPE_ACTIVITY_DETAIL, new Integer(
				GraphicalDataHelper.ACTIVITY_DETAIL_DIAGRAM));
		typeMap.put(ResourceHelper.DIAGRAM_TYPE_WP_DEPENDENCY, new Integer(
				GraphicalDataHelper.WORK_PRODUCT_DEPENDENCY_DIAGRAM));
	}

	public static int getIntType(String diagramType) {
		Integer type = (Integer) typeMap.get(diagramType);
		if (type != null) {
			return type.intValue();
		}

		return -1;
	}

	Shell shell = null;

	public ActivityDiagramService() {
		this(null, new File(LibraryService.getInstance().getCurrentMethodLibraryPath()));
	}

	public ActivityDiagramService(File pubDir) {
		this(null, pubDir);
	}

	public ActivityDiagramService(Composite parent, File pubDir) {
		this.parent = parent;
		this.pubDir = pubDir;
	}

	private AbstractDiagramGraphicalViewer getDiagramViewer(int diagramType) {
		// if the shell window is distroyed, recreate it
		if ((this.shell != null) && this.shell.isDisposed()) {
			this.parent = null;
			this.shell = null;
		}

		getViewerHolder(parent);

		switch (diagramType) {
		case GraphicalDataHelper.ACTIVITY_DIAGRAM:
			return new ActivityDiagramViewer(holder);

		case GraphicalDataHelper.ACTIVITY_DETAIL_DIAGRAM:
			return new ActivityDetailDiagramViewer(holder);

		case GraphicalDataHelper.WORK_PRODUCT_DEPENDENCY_DIAGRAM:
			return new WPDependencyDiagramViewer(holder);

		default:
			return null;
		}
	}

	private void getViewerHolder(Composite parent) {
		if (parent == null) {
			if (shell == null || shell.isDisposed()) {
				shell = createShell();
			}
			shell.open();
			parent = shell;
		}

		if (holder != null) {
			holder.dispose();
		}

		holder = new Composite(parent, SWT.NONE);
		holder.setLayoutData(new GridData(1, 1)); // size can't be 0,0
		// otherwise the diagram
		// will not be painted
		holder.setLayout(new GridLayout());
		holder.setVisible(false);
	}

	private Shell createShell() {
		Shell shell = null;
		Display d = Display.getDefault();
		shell = new Shell(d);
		GridLayout layout = new GridLayout();
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		shell.setLayout(layout);
		shell.setBounds(0, 0, 0, 0);
		shell.setVisible(false);
		return shell;
	}

	public void dispose() {
		if ((shell != null) && (!shell.isDisposed())) {
			shell.close();
			shell.dispose();
		}
	}

	/**
	 * save the element diagram image and returns the image file url.
	 * 
	 * @param wrapper
	 * @param imgPath
	 * @param diagramType
	 * @param filter
	 *            IFilter
	 * @param sup
	 *            Suppression
	 * @return String the image path relative to the publishing dir
	 * 
	 * @see org.eclipse.epf.library.layout.diagram.IActivityDiagramService#saveDiagram(java.lang.Object, java.lang.String, java.lang.String, org.eclipse.epf.library.edit.IFilter, org.eclipse.epf.library.edit.util.Suppression)
	 */
	public DiagramInfo saveDiagram(final Object wrapper, final String imgPath, 
			final String diagramType, final IFilter filter,
			final Suppression sup) {
		// initialize the diagramInfo
		diagramInfo = null;

		// grab the UI thread to avoid thread access error
		SafeUpdateController.syncExec(new Runnable() {
			public void run() {
				__internal_saveDiagram(wrapper, imgPath, diagramType, filter, sup);
			}
		});

		return diagramInfo;
	}

	private boolean hasUserDefinedDiagram(Activity e, String imgPath, String diagramType) throws Exception
	{		
		// if there is a user defined diagram, use it
		org.eclipse.epf.diagram.model.util.DiagramInfo info = new org.eclipse.epf.diagram.model.util.DiagramInfo((Activity)e);
		switch (getIntType(diagramType))
		{
			case GraphicalDataHelper.ACTIVITY_DIAGRAM:
				if ( info.canPublishADImage() )
				{
					return (info.getActivityDiagram() != null) && info.canPublishADImage();
				}
				break;
	
			case GraphicalDataHelper.ACTIVITY_DETAIL_DIAGRAM:
				if ( info.canPublishADDImage() )
				{
					return (info.getActivityDetailDiagram() != null) && info.canPublishADDImage();
				}
				break;
							
			case GraphicalDataHelper.WORK_PRODUCT_DEPENDENCY_DIAGRAM:
				if ( info.canPublishWPDImage() )
				{
					return (info.getWPDDiagram() != null ) && info.canPublishWPDImage();
				}
				break;

			default:
				break;
		}
		
		return false;
	}
	
	private void __internal_saveDiagram(Object wrapper, final String imgPath, String diagramType,
			IFilter filter, Suppression sup) {
		
		if ( sup.isSuppressed(wrapper) ) {
			return;
		}
		
		Object o = TngUtil.unwrap(wrapper);
		if (!(o instanceof Activity)) {
			return;
		}

		//MethodElement e = (MethodElement)o;
		Activity e = (Activity)o;
		// DiagramInfo diagramInfo = null;
		Image image = null;
		int type = getIntType(diagramType);
		if (type < 0) {
			return;
		}

		AbstractDiagramGraphicalViewer viewer = null;

		// keep the dirty flag and reset back to avoid make the library dirty
		boolean dirtyFlag = e.eResource().isModified();

		try {
			if ( hasUserDefinedDiagram((Activity)e, imgPath, diagramType) )
			{
				return;
			}


			// first check if we need to generate the diagram or not
			// if the diagram is supressed, don't generate diagram
			// don't create the diagram if it's not there,
			// id the diagram does not exist, it's supressed
			org.eclipse.epf.uma.Diagram d = GraphicalDataManager.getInstance()
					.getUMADiagram((Activity) e, type, false);

			// Allow the option to publish 'uncreated' diagrams
			// by default, uncreated activity detail diagrams will be published,
			// uncreated diagrams of other types will not be published
			boolean exist = (d != null);
			if (exist) {
				if (d.getSuppressed().booleanValue() == true)
					return;
				
				// If an extension has its own diagram. Base is replaced or contributed. 
				// extension diagram shows realized element in undefined location. 
				// In publishing don't display extension diagram even if it has its own
				// diagram if realized elements are coming in through variability.
				if(type == GraphicalDataHelper.ACTIVITY_DIAGRAM &&
						checkVariability(e, filter,type) != null){
					return;
				}
					
			}else{
				
				if((type == GraphicalDataHelper.WORK_PRODUCT_DEPENDENCY_DIAGRAM))
					return;

				// For Activity Diagram un opened extension publish.
				if(type == GraphicalDataHelper.ACTIVITY_DIAGRAM){
					// If option is not checked, don't generate a diagram
					if(!publishADForActivityExtension) return;
					
					//If extension is modified don't generate it.
					if(!e.getBreakdownElements().isEmpty())
						return;
					VariabilityElement calculatedBase = checkVariability(e, filter, type);
					if(calculatedBase == null) {
						return;
					}	
					
					wrapper = calculatedBase;
					e = (Activity)calculatedBase;
					exist = true;
				}
				
				if (publishUncreatedADD == false && type == GraphicalDataHelper.ACTIVITY_DETAIL_DIAGRAM){
					boolean contributorexist = false;
					// This is need, if contributor has a ADD diagra, base don't 
					// base should generate ADD in browsing.
					MethodConfiguration config = null;
					if (filter instanceof ProcessAdapterFactoryFilter) {
						config = ((ProcessAdapterFactoryFilter) filter)
								.getMethodConfiguration();
					}
					if (config == null)
						return;

					// Get immediate contributors first, and check immediate contributors
					// have anything extra breakdown elements.
					List list = ConfigurationHelper.getContributors(e, config);
					if(e instanceof Activity){
						Iterator iterator = list.iterator();
						if(iterator != null){
							while(iterator.hasNext()){
								Object act = iterator.next();
								if(act != null){
									org.eclipse.epf.uma.Diagram dx = GraphicalDataManager.getInstance()
									.getUMADiagram((Activity) act, type, false);
									if(dx != null){   
										contributorexist = true;
										break;
									}
								}
							}
						}
					}
					if(!contributorexist)
					return;
				}
			}
			
			try {
				viewer = getDiagramViewer(type);
				viewer.loadDiagram(wrapper, !exist, filter, sup);
				diagramInfo = viewer.getDiagramInfo();
				if (diagramInfo != null && !diagramInfo.isEmpty()) {
					image = viewer.createDiagramImage();
					if (image != null) {
						// save the image
						File f = new File(pubDir, imgPath);

						// make sure the file is created otherwise exception
						File parent = f.getParentFile();
						if (!parent.exists()) {
							parent.mkdirs();
						}

						if (!f.exists()) {
							f.createNewFile();
						}
						OutputStream os = new FileOutputStream(f);
						ImageLoader loader = new ImageLoader();
						loader.data = new ImageData[] { image.getImageData() };
						loader.save(os, SWT.IMAGE_JPEG);

						diagramInfo.setImageFilePath(imgPath);
					} else {
						System.out.println("Unable to create diagram image"); //$NON-NLS-1$
					}
				}
			} catch (RuntimeException e1) {
				e1.printStackTrace();
			}

			// delete the newly created diagram from the library
			if (!exist) {
				d = GraphicalDataManager.getInstance().getUMADiagram(
						(Activity) e, type, false);
				if (d != null) {
					EcoreUtil.remove(d);
				}
			}

		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {

				// restore the dirty flag
				e.eResource().setModified(dirtyFlag);

				if (viewer != null) {
					viewer.dispose();
				}
				if (image != null) {
					image.dispose();
				}
			} catch (RuntimeException e1) {
				e1.printStackTrace();
			}
		}

	}


private VariabilityElement checkVariability(VariabilityElement e, IFilter filter,
			int type) {

		MethodConfiguration config = null;
		if (filter instanceof ProcessAdapterFactoryFilter) {
			config = ((ProcessAdapterFactoryFilter) filter)
					.getMethodConfiguration();
		}
		if (config == null)
			return null;

		// Get immediate contributors first, and check immediate contributors
		// have anything extra breakdown elements.
		List list = ConfigurationHelper.getContributors(e, config);
		for (Iterator iterator = list.iterator(); iterator.hasNext();) {
			Object next = iterator.next();
			if (next instanceof Activity) {
				if (!((Activity) next).getBreakdownElements().isEmpty())
					return null;
			}
		}

		// Get all Contributors from parent chain and contributor chain for the
		// element e.
		VariabilityInfo eInfo = ((ProcessAdapterFactoryFilter) filter)
				.getVariabilityInfo((VariabilityElement) e);
		List contributors = eInfo.getContributors();

		VariabilityElement ve = e.getVariabilityBasedOnElement();
		if (ve == null) {
			return null;
		}
		
		Activity replacer = (Activity) ConfigurationHelper.getReplacer(ve,
				config);
		if (replacer != null) {
			ve = replacer;
			org.eclipse.epf.uma.Diagram replacerDiagram = GraphicalDataManager
					.getInstance().getUMADiagram(replacer, type, false);
			if (replacerDiagram != null) {
				//anyReplacer.add(replacer);
				return replacer;
			} else {
				return null;
			}
		} else {
			org.eclipse.epf.uma.Diagram baseDiagram = GraphicalDataManager
					.getInstance()
					.getUMADiagram((Activity) ve, type, false);
			if (baseDiagram != null) {
				
				// Check first if baseDiagram is suppressed.
				if (baseDiagram.getSuppressed().booleanValue() == true)
					return null;
				
				// Find the contributors of Base
				VariabilityInfo veInfo = ((ProcessAdapterFactoryFilter) filter)
						.getVariabilityInfo((VariabilityElement) ve);
				List veContributors = veInfo.getContributors();
				if (contributors.size() != veContributors.size()) {
					for (Iterator iterator = contributors.iterator(); iterator
							.hasNext();) {
						Object next = iterator.next();
						if (!veContributors.contains(next)) {
							if (!((Activity) next).getBreakdownElements()
									.isEmpty()) {
								return null;
							}
						}
					}
				}
				
				return ve;
				
			}else{
				// If no base diagram, check base of base had any diagram.
				return checkVariability(ve, filter, type);
			}
		}
		
	}

	/**
	 * Set the window's preference attribute for Activity Detail Diagram.
	 * 
	 */
	public void setPublishedUnCreatedADD(boolean flag) {
		this.publishUncreatedADD = flag;
	}
	/**
	 * Set the window's preference attribute for Acitivyt Diagram
	 * 
	 */
	
	public void setPublishADForActivityExtension(boolean flag){
		this.publishADForActivityExtension = flag;
	}

}