//------------------------------------------------------------------------------
// 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.layout.diagram;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.TexturePaint;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Iterator;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

import org.eclipse.core.runtime.Platform;
import org.eclipse.epf.common.utils.I18nUtil;
import org.eclipse.epf.common.utils.ImageUtil;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.LibraryResources;
import org.eclipse.epf.library.layout.IElementLayout;
import org.eclipse.epf.library.layout.elements.RoleLayout;
import org.eclipse.epf.uma.Role;
import org.eclipse.epf.uma.Task;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.swt.SWT;


/**
 * Renders the Role diagram using Java2D and saves it as a JPEG file.
 * 
 * @author Kelvin Low
 * @author Jinhua Xi
 * @since 1.0
 */
public class RoleDiagramPublisher {

	private static final String DEFAULT_FONT_NAME = "Arial"; //$NON-NLS-1$

	private static final int DEFAULT_FONT_SIZE = 10;

	private static final int DEFAULT_X_MARGIN = 200;	
	
	private static final int DEFAULT_X_SPACING = 70;

	private static final int DEFAULT_Y_SPACING = 30;

	// The maximum width of the generated image.
	private int maxImageWidth = 1024;

	// The maximum height of the generated image.
	private int maxImageHeight = 1024;

	// The border width.
	private int borderWidth = 10;

	// The border height.
	private int borderHeight = 10;

	// The additional spacing before the left-most Task and/or Work Product
	// image.
	private int xMargin = 240;

	// The horizontal spacing between the element images.
	private int xSpacing = 45;

	// The vertical spacing between the element images.
	private int ySpacing = 40;

	private int linePadding = 12;

	private Font textFont = null;

	/**
	 * Creates a new <code>ImagePublisher</code>.
	 */
	public RoleDiagramPublisher() {
		// Select the font for rendering the element names.
		String fontName;
		int fontSize;
		if (SWT.getPlatform().equals(Platform.WS_WIN32)) {
			fontName = LibraryResources.roleDiagramFont_name_win32;
			fontSize = I18nUtil.getInt(LibraryResources.roleDiagramFont_size_win32, DEFAULT_FONT_SIZE); 
		} else {
			fontName = LibraryResources.roleDiagramFont_name;		
			fontSize = I18nUtil.getInt(LibraryResources.roleDiagramFont_size, DEFAULT_FONT_SIZE); 
		}
		if (fontName.startsWith("[")) { //$NON-NLS-1$
			fontName = DEFAULT_FONT_NAME;
		}
		textFont = new Font(fontName, Font.PLAIN, fontSize);

		xMargin = I18nUtil.getInt(LibraryResources.roleDiagram_xMargin, DEFAULT_X_MARGIN); 
		xSpacing = I18nUtil.getInt(LibraryResources.roleDiagram_xSpacing, DEFAULT_X_SPACING); 
		ySpacing = I18nUtil.getInt(LibraryResources.roleDiagram_ySpacing, DEFAULT_Y_SPACING); 
	}

	/**
	 * Generates the Role Diagram HTML source for the given role.
	 * 
	 * @param role
	 *            The Role element.
	 * @param path
	 *            The publish path.
	 * @return A <code>MethodElementDiagram</code> object associated with the
	 *         published diagram.
	 */
	public MethodElementDiagram publish(RoleLayout roleLayout, File path) {

		Role role = (Role) roleLayout.getElement();

		if (role == null) {
			throw new IllegalArgumentException();
		}

		try {
			MethodElementDiagram elementDiagram = new MethodElementDiagram(role);

			String publishDir = roleLayout.getLayoutMgr().getPublishDir();
			String mapName = roleLayout.getDisplayName();
			if (mapName == null || mapName.length() == 0) {
				mapName = "Unknown"; //$NON-NLS-1$
			} else {
				mapName = mapName.replace(' ', '_');
			}
			HTMLMap htmlMap = new HTMLMap(mapName);
			elementDiagram.setHTMLMap(htmlMap);

			// Create the AWT JPanel for rendering the diagram.
			JPanel panel = new JPanel();

			// Create the output BufferedImage.
			BufferedImage outputImage = new BufferedImage(maxImageWidth,
					maxImageHeight, BufferedImage.TYPE_INT_RGB);
			Graphics2D g2d = (Graphics2D) outputImage.getGraphics();

			// Switch on anti-aliasing.
			g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
					RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			g2d.fillRect(0, 0, maxImageWidth, maxImageHeight);

			// Set the stroke for drawing the association lines.
			g2d.setStroke(new BasicStroke(1.25f));
			g2d.setColor(Color.BLACK);

			int xOffset = xSpacing / 2;

			// Renders the Tasks performed by the Role.
			List tasks = roleLayout.getPerforms();
			int totalTasks = tasks != null ? tasks.size() : 0;
			Point taskStartPoint = new Point(borderWidth + xMargin,
					borderHeight);
			Point taskEndPoint = new Point(borderWidth + xMargin, borderHeight);
			int x = taskStartPoint.x;
			int y = taskStartPoint.y;
			int tasksEndX = 0;
			if (totalTasks > 0) {
				int taskNo = 1;
				for (Iterator i = tasks.iterator(); i.hasNext(); taskNo++) {
					Task task = (Task) i.next();

					IElementLayout taskLayout = roleLayout.getLayoutMgr()
							.getLayout(task, true);

					String taskName = taskLayout.getDisplayName();
					String imageFile = publishDir
							+ taskLayout.getDiagramiconUrl();
					try {
						BufferedImage taskImage = ImageUtil.getBufferedImage(
								imageFile, panel);
						int taskWidth = taskImage.getWidth();
						int taskHeight = taskImage.getHeight();
						if (taskNo == 1) {
							taskEndPoint.x += taskWidth;
							taskEndPoint.y += taskHeight;
							tasksEndX = taskEndPoint.x;
						}
						Rectangle taskImageRect = new Rectangle(x, y,
								taskWidth, taskHeight);
						TexturePaint taskPaint = new TexturePaint(taskImage,
								taskImageRect);
						g2d.setPaint(taskPaint);
						g2d.fill(taskImageRect);
						if (taskName != null) {
							ImageUtil.drawText(g2d, taskName, textFont,
									Color.BLACK, x - xOffset, taskEndPoint.y,
									taskWidth + xSpacing);
						}

						String href = taskLayout.getFilePath(roleLayout)
								+ taskLayout.getFileName(".html"); //$NON-NLS-1$
						HTMLArea htmlArea = new HTMLArea(task.getGuid(), href,
								"rect", taskImageRect, taskName); //$NON-NLS-1$
						htmlMap.addArea(htmlArea);

						if (x + taskWidth > tasksEndX) {
							tasksEndX = x + taskWidth;
						}

						if (i.hasNext()) {
							int xIncrement = taskWidth + xSpacing;
							x += xIncrement;
							taskEndPoint.x += xIncrement;
							if ((x + xIncrement + xOffset + borderWidth) > maxImageWidth) {
								x = taskStartPoint.x;
								int yIncrement = taskHeight + ySpacing;
								y += yIncrement;
								taskEndPoint.y += yIncrement;
								taskEndPoint.x = taskStartPoint.x + taskWidth;
							}
						}
					} catch (Exception e) {
						LibraryPlugin.getDefault().getLogger().logError(e);
					}
				}
			}

			// Renders the Work Products that the Role is responsible for.
			List workProducts = roleLayout.getResponsibleFor();
			int totalWorkProducts = workProducts != null ? workProducts.size()
					: 0;
			Point workProductStartPoint = new Point(taskStartPoint.x,
					borderHeight);
			Point workProductEndPoint = new Point(taskStartPoint.x,
					borderHeight);
			if (totalTasks > 0 && totalWorkProducts > 0) {
				workProductStartPoint.y = taskEndPoint.y + ySpacing + ySpacing
						/ 2;
				workProductEndPoint.y = workProductStartPoint.y;
			} else if (totalTasks > 0) {
				workProductEndPoint.y = taskEndPoint.y + borderHeight;
			}
			x = workProductStartPoint.x;
			y = workProductStartPoint.y;
			int workProductsEndX = 0;
			if (totalWorkProducts > 0) {
				int workProductNo = 1;
				for (Iterator i = workProducts.iterator(); i.hasNext(); workProductNo++) {
					WorkProduct workProduct = (WorkProduct) i.next();

					IElementLayout wpLayout = roleLayout.getLayoutMgr()
							.getLayout(workProduct, true);

					String workProductName = wpLayout.getDisplayName();
					String imageFile = publishDir
							+ wpLayout.getDiagramiconUrl();
					try {
						BufferedImage workProductImage = ImageUtil
								.getBufferedImage(imageFile, panel);
						int workProductWidth = workProductImage.getWidth();
						int workProductHeight = workProductImage.getHeight();
						if (workProductNo == 1) {
							workProductEndPoint.x += workProductWidth;
							workProductEndPoint.y += workProductHeight;
							workProductsEndX = workProductEndPoint.x;
						}
						Rectangle workProductImageRect = new Rectangle(x, y,
								workProductWidth, workProductHeight);
						TexturePaint workProductPaint = new TexturePaint(
								workProductImage, workProductImageRect);
						g2d.setPaint(workProductPaint);
						g2d.fill(workProductImageRect);
						if (workProductName != null) {
							ImageUtil.drawText(g2d, workProductName, textFont,
									Color.BLACK, x - xOffset,
									workProductEndPoint.y, workProductWidth
											+ xSpacing);
						}

						String href = wpLayout.getFilePath(roleLayout)
								+ wpLayout.getFileName(".html"); //$NON-NLS-1$

						HTMLArea htmlArea = new HTMLArea(workProduct.getGuid(), href,
								"rect", workProductImageRect, workProductName); //$NON-NLS-1$
						htmlMap.addArea(htmlArea);

						if (x + workProductWidth > workProductsEndX) {
							workProductsEndX = x + workProductWidth;
						}

						if (i.hasNext()) {
							int xIncrement = workProductWidth + xSpacing;
							x += xIncrement;
							workProductEndPoint.x += xIncrement;
							if ((x + xIncrement + xOffset + borderWidth) > maxImageWidth) {
								x = workProductStartPoint.x;
								int yIncrement = workProductHeight + ySpacing;
								y += yIncrement;
								workProductEndPoint.y += yIncrement;
								workProductEndPoint.x = workProductStartPoint.x
										+ workProductWidth;
							}
						}
					} catch (Exception e) {
						LibraryPlugin.getDefault().getLogger().logError(e);
					}
				}
			}

			// Render the Role.
			Point roleStartPoint = new Point(xOffset-5, borderHeight);
			Point roleEndPoint = roleStartPoint;			
			try {
				String roleName = roleLayout.getDisplayName();
				String imageFile = publishDir + roleLayout.getDiagramiconUrl();
				BufferedImage roleImage = ImageUtil.getBufferedImage(imageFile,
						panel);
				int roleWidth = roleImage.getWidth();
				int roleHeight = roleImage.getHeight();
				x = xOffset-5;
				y = borderHeight;
				roleEndPoint.x += roleWidth;
				roleEndPoint.y += roleHeight;
				if (totalWorkProducts > 0) {
					y = borderHeight
							+ (workProductEndPoint.y - taskStartPoint.y - roleHeight)
							/ 2;

					// Render the "responsible for" association line.
					Point startPoint = new Point(x + roleWidth + linePadding
							/ 2, y + roleHeight / 2);
					Point endPoint = new Point(workProductStartPoint.x
							- linePadding, workProductStartPoint.y
							+ (workProductEndPoint.y - workProductStartPoint.y)
							/ 2);
					renderAssociation(
							g2d,
							startPoint,
							endPoint,
							LibraryResources.roleDiagramResponsibleFor_text, textFont, Color.BLACK);
				} else if (totalTasks > 0) {
					y = borderHeight
							+ (taskEndPoint.y - taskStartPoint.y - roleHeight)
							/ 2;
				}
				roleStartPoint.y = y;
				roleEndPoint.y = y + roleHeight;

				if (totalTasks > 0) {
					// Render the "performs" association line.
					Point startPoint = new Point(x + roleWidth + linePadding
							/ 2, y + roleHeight / 2);
					Point endPoint = new Point(taskStartPoint.x - linePadding,
							borderHeight + (taskEndPoint.y - taskStartPoint.y)
									/ 2);
					renderAssociation(
							g2d,
							startPoint,
							endPoint,
							LibraryResources.roleDiagramPerforms_text, textFont, Color.BLACK);
				}
				Rectangle roleImageRect = new Rectangle(x, y, roleWidth,
						roleHeight);
				TexturePaint rolePaint = new TexturePaint(roleImage,
						roleImageRect);
				g2d.setPaint(rolePaint);
				g2d.fill(roleImageRect);
				if (roleName != null) {
					ImageUtil.drawText(g2d, roleName, textFont, Color.BLACK, x - xOffset,
							y + roleHeight, roleWidth + xSpacing);
				}
			} catch (Exception e) {
				LibraryPlugin.getDefault().getLogger().logError(e);
			}

			// Calculate the optimal width and height for the rendered image.
			int optimalWidth = Math.max(tasksEndX, workProductsEndX)
					+ borderWidth;
			optimalWidth = Math
					.max(optimalWidth, roleEndPoint.x + borderWidth);
			
			optimalWidth = Math.min(optimalWidth, maxImageWidth);
			
			int optimalHeight = workProductEndPoint.y + borderHeight;
			optimalHeight = Math.max(optimalHeight, roleEndPoint.y
					+ borderHeight);
			optimalWidth += xOffset;
			optimalHeight += 20;
			
			optimalHeight = Math.min(optimalHeight, maxImageHeight);
			BufferedImage optimalImage = outputImage.getSubimage(0, 0,
					optimalWidth, optimalHeight);

			// Save the image as a JPEG file.
			File jpgFile = new File(path, roleLayout.getFilePath()
					+ roleLayout.getFileName(".jpg")); //$NON-NLS-1$
			File parentFolder = jpgFile.getParentFile();
			if (!parentFolder.exists()) {
				parentFolder.mkdirs();
			}
			ImageIO.write(optimalImage, "jpg", jpgFile); //$NON-NLS-1$
			elementDiagram.setImageFileName(jpgFile.getName());
			return elementDiagram;
		} catch (Exception e) {
			LibraryPlugin.getDefault().getLogger().logError(e);
			return null;
		}
	}

	/**
	 * Renders the association line.
	 * 
	 * @param g2d
	 *            The Graphics2D context.
	 * @param startPoint
	 *            The start point of the line.
	 * @param endPoint
	 *            The end point of the line.
	 * @param name
	 *            The association name.
	 * @param font
	 *            The font for rendering the association name.
	 * @param color
	 *            the color for rendering the association name.
	 */
	protected void renderAssociation(Graphics2D g2d, Point startPoint,
			Point endPoint, String name, Font font, Color color) {
		g2d.draw(new Line2D.Double(startPoint.x, startPoint.y, endPoint.x,
				endPoint.y));
		int textX = startPoint.x + (endPoint.x - startPoint.x) / 2 - 40;
		int textY = startPoint.y + (endPoint.y - startPoint.y) / 2 - 5;
		if (startPoint.y != endPoint.y) {
			g2d.setColor(Color.WHITE);
			g2d.fillRect(textX, textY, 80, 10);
		} else {
			textY -= 10;
		}
		ImageUtil.drawText(g2d, name, font, color, textX, textY, 80);
	}

}
