/*******************************************************************************
 * Copyright (c) 2006 Sybase, Inc. 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:
 *     Sybase, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.pagedesigner.css2.layout;

import java.util.List;

import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jst.jsf.common.ui.internal.logging.Logger;
import org.eclipse.jst.pagedesigner.PDPlugin;
import org.eclipse.jst.pagedesigner.css2.property.TextDecorationMeta;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;

/**
 * @author mengbo
 */
public class TextLayoutSupport {
	private static final Logger _log = PDPlugin
			.getLogger(TextLayoutSupport.class);

	private static final String[] DELIMITERS = { "\r\n", //$NON-NLS-1$
			"\n", //$NON-NLS-1$
			"\r" //$NON-NLS-1$
	}; //$NON-NLS-1$

	static private int delimeterLength;

	/**
	 * Reuses an existing <code>TextFragmentBox</code>, or creates a new one.
	 * 
	 * @param i
	 *            the index
	 * @param fragments
	 *            the original list of fragments
	 * @return a TextFragmentBox
	 */
	// copied from TextLayout
	protected static TextFragmentBox getFragment(int i, List fragments) {
		if (fragments.size() > i) {
			return (TextFragmentBox) fragments.get(i);
		}
		TextFragmentBox box = new TextFragmentBox();
		fragments.add(box);
		return box;
	}

	/**
	 * Returns the average character width of given TextFragmentbox
	 * 
	 * @param fragment
	 *            the TextFragmentBox
	 * @return the average character width
	 */
	public static float getAverageCharWidth(TextFragmentBox fragment) {
		if (fragment._width != 0 && fragment._length != 0) {
			return fragment._width / (float) fragment._length;
		}
		return 0.0f;
	}

	// ----------------------------------------------------------------------------------------
	/**
	 * this method will create a set of TextFragment. Each fragment will offset
	 * to the original text (whole text for the text figure).
	 * @param context 
	 * @param text 
	 * @param fragments 
	 * @param font 
	 * @param wrappingStyle 
	 * @param trimLeading 
	 */
	public static void layoutNormal(FlowContext context, String text,
			List fragments, Font font, int wrappingStyle, boolean trimLeading) {
		int i = 0; // The index of the current fragment;
		int offset = 0;
		if (trimLeading) {
			offset = 1;
			text = text.substring(1);
		}

		int length = 0; // The length of the current fragment
		float prevAvgCharWidth;
		LineBox currentLine;
		TextFragmentBox fragment;

		while (text.length() > 0) {
			fragment = null;
			prevAvgCharWidth = 0f;
			fragment = getFragment(i, fragments);
			prevAvgCharWidth = getAverageCharWidth(fragment);

			// Check for newline, if it exists, call context.endLine and skip
			// over the newline
			// Exccept for first time through, don't do this.
			if (i != 0) {
				boolean changed = false;
				if (text.charAt(0) == '\r') {
					text = text.substring(1);
					changed = true;
					offset += 1;
				}
				if (text.length() != 0 && text.charAt(0) == '\n') {
					text = text.substring(1);
					changed = true;
					offset += 1;
				}
				if (changed) {
					context.endLine();
				}
			}

			fragment._offset = offset;

			// This loop is done at most twice.
			// The second time through, a context.endLine()
			// was requested, and the loop will break.
			while (true) {
				currentLine = context.getCurrentLine();
				length = FlowUtilities.setupFragmentBasedOnTextSpace(fragment,
						text, font, currentLine.getAvailableWidth(),
						prevAvgCharWidth, wrappingStyle);

				if (fragment._width <= currentLine.getAvailableWidth()
						|| !context.isCurrentLineOccupied()) {
					break;
				}
				context.endLine();
			}
			// fragment.x = context.getCurrentX();
			context.addToCurrentLine(fragment);
			text = text.substring(length);
			offset += length;
			if (text.length() > 0) {
				context.endLine();
			}
			i++;
		}

		// Remove the remaining unused fragments.
		while (i < fragments.size()) {
			fragments.remove(fragments.size() - 1);
		}
	}

	/**
	 * @param context
	 * @param text
	 * @param fragments
	 * @param font
	 */
	public static void layoutNoWrap(FlowContext context, String text,
			List fragments, Font font) {
		TextFragmentBox fragment;
		int i = 0;
		int offset = 0;

		while (offset < text.length()) {
			int result = nextLineBreak(text, offset);
			fragment = getFragment(i++, fragments);
			fragment._length = result - offset;
			fragment._offset = offset;
			FlowUtilities.setupFragment(fragment, font, text.substring(offset));
			context.getCurrentLine().add(fragment);
			offset = result + delimeterLength;
			if (delimeterLength != 0) {
				// in nextLineBreak we fo
				context.endLine();
			}

		}
		// Remove the remaining unused fragments.
		while (i < fragments.size()) {
			fragments.remove(i++);
		}
	}

	private static int nextLineBreak(String text, int offset) {
		int result = text.length();
		delimeterLength = 0;
		int current;
		for (int i = 0; i < DELIMITERS.length; i++) {
			current = text.indexOf(DELIMITERS[i], offset);
			if (current != -1 && current < result) {
				result = current;
				delimeterLength = DELIMITERS[i].length();
			}
		}
		return result;
	}

	/**
	 * @param g
	 * @param fragments
	 * @param font
	 * @param textDecoration
	 */
	public static void paintTextFigure(Graphics g, List fragments, Font font,
			int textDecoration) {
		paintTextFigure(g, fragments, font, null, textDecoration);
	}

	/**
	 * @param g
	 * @param rect
	 * @param textDecoration
	 */
	public static void paintTextDecoration(Graphics g, Rectangle rect,
			int textDecoration) {
		if ((textDecoration & TextDecorationMeta.UNDERLINE) != 0) {
			g.drawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width
					- 1, rect.y + rect.height - 1);
		}
		if ((textDecoration & TextDecorationMeta.OVERLINE) != 0) {
			g.drawLine(rect.x, rect.y + 1, rect.x + rect.width - 1, rect.y + 1);
		}
		if ((textDecoration & TextDecorationMeta.LINETHROUGH) != 0) {
			g.drawLine(rect.x, rect.y + rect.height / 2, rect.x + rect.width
					- 1, rect.y + rect.height / 2);
		}
	}

	/**
	 * @param g
	 * @param fragments
	 * @param font
	 * @param color
	 * @param textDecoration
	 */
	public static void paintTextFigure(Graphics g, List fragments, Font font,
			Color color, int textDecoration) {
		// FIXME: It happens there is problem in this method's parameters. what
		// exception should be catched?
		try {
			TextFragmentBox frag;
			// XXX: adjust font. Here is not using setFont(), because that will
			// result in revalidate
			g.setFont(font);

			for (int i = 0; i < fragments.size(); i++) {
				frag = (TextFragmentBox) fragments.get(i);
				// if (!g.getClip(Rectangle.SINGLETON).intersects(frag))
				// continue;
				String draw;
				draw = frag.getTextData();

				if (color != null) {
					g.setForegroundColor(color);
				}
				g.drawText(draw, frag._x, frag._y);
				if ((textDecoration & TextDecorationMeta.UNDERLINE) != 0) {
					g.drawLine(frag._x, frag._y + frag.getHeight() - 1, frag._x
							+ frag.getWidth(), frag._y + frag.getHeight() - 1);
				}
				if ((textDecoration & TextDecorationMeta.OVERLINE) != 0) {
					g.drawLine(frag._x, frag._y, frag._x + frag.getWidth(),
							frag._y);
				}
				if ((textDecoration & TextDecorationMeta.LINETHROUGH) != 0) {
					g.drawLine(frag._x, frag._y + frag.getHeight() / 2, frag._x
							+ frag.getWidth(), frag._y + frag.getHeight() / 2);
				}

				if (Debug.DEBUG_BASELINE) {
					g.drawLine(frag._x, frag._y + frag.getAscent(), frag._x
							+ frag.getWidth(), frag._y + frag.getAscent());
				}
			}
		} catch (Exception e) {
			// "Error in text painting:"
			_log.info("TextLayoutSupport.Info.1", e); //$NON-NLS-1$
		}
	}

	/**
	 * 
	 * @param g
	 * @param fragments
	 * @param text
	 *            all the text in the Text figure.
	 * @param font
	 * @param color
	 * @param textDecoration
	 * @param start
	 * @param end
	 * @param selectionForeColor
	 * @param selectionBackColor
	 */
	public static void paintTextFigureWithSelection(Graphics g, List fragments,
			String text, Font font, Color color, int textDecoration, int start,
			int end, Color selectionForeColor, Color selectionBackColor) {
		// FIXME: It happens there is problem in this method's parameters. what
		// exception should be catched?
		try {
			TextFragmentBox frag;

			Color originalForeground = g.getForegroundColor();
			Color originalBackgroud = g.getBackgroundColor();

			// XXX: adjust font. Here is not using setFont(), because that will
			// result in revalidate
			g.setFont(font);

			for (int i = 0, n = fragments.size(); i < n; i++) {
				frag = (TextFragmentBox) fragments.get(i);

				// to make things simpler, we always draw the line using default
				// color
				if (color != null) {
					g.setForegroundColor(color);
				}

				// if (!g.getClip(Rectangle.SINGLETON).intersects(frag))
				// continue;
				String draw;
				draw = frag.getTextData();
				if (frag._offset >= end || frag._offset + frag._length <= start) {
					// we are not in selection. no need to change color
					g.drawText(draw, frag._x, frag._y);
					paintTextDecoration(g, frag.getRectangle(), textDecoration);
				} else if (frag._offset >= start
						&& frag._offset + frag._length <= end) {
					// we are fully in selection
					g.setForegroundColor(selectionForeColor);
					g.setBackgroundColor(selectionBackColor);
					g
							.fillRectangle(frag._x, frag._y, FlowUtilities
									.getTextExtents(draw, font).width, frag
									.getHeight());
					g.drawText(draw, frag._x, frag._y);
					paintTextDecoration(g, frag.getRectangle(), textDecoration);
				} else {
					// partial of the fragment's text is in selection.

					// draw the original string first
					g.drawText(draw, frag._x, frag._y);
					// then override with the selected parts.
					g.setForegroundColor(selectionForeColor);
					g.setBackgroundColor(selectionBackColor);
					int partialStart = frag._offset > start ? frag._offset
							: start;
					int partialEnd = (frag._offset + frag._length > end) ? end
							: (frag._offset + frag._length);
					int x = 0;
					String skip = text.substring(frag._offset, partialStart);
					x = FlowUtilities.getTextExtents(skip, font).width;
					String todraw = text.substring(partialStart, partialEnd);
					if (todraw.length() > 0) {
						Dimension dimension = FlowUtilities.getTextExtents(skip
								+ todraw, font);
						g.fillRectangle(frag._x + x, frag._y, dimension.width
								- x, dimension.height);
						g.drawText(skip + todraw, frag._x, frag._y);
						if (color != null) {
							g.setForegroundColor(color);
						} else {
							g.setForegroundColor(originalForeground);
						}
						g.drawText(skip, frag._x, frag._y);
						paintTextDecoration(g, frag.getRectangle(),
								textDecoration);
						g.setForegroundColor(selectionForeColor);
						paintTextDecoration(g,
								new Rectangle(frag._x + x, frag._y,
										dimension.width - x, dimension.height),
								textDecoration);
					}
				}

				// we do this in each loop, to make sure we are using correct
				// color
				g.setForegroundColor(originalForeground);
				g.setBackgroundColor(originalBackgroud);

			}
		} catch (Exception e) {
			// "Error in text painting:"
			_log.info("TextLayoutSupport.Info.1", e); //$NON-NLS-1$
		}
	}

	/**
	 * @param textAlign
	 * @param rect
	 * @param textWidth
	 * @return the x value
	 */
	public static int getBeginX(Object textAlign, Rectangle rect, int textWidth) {
		int x = rect.x;
		if (textAlign != null) {
			String align = textAlign.toString();
			if ("left".equalsIgnoreCase(align)) //$NON-NLS-1$
			{
				x = rect.x + 1;
			} else if ("right".equalsIgnoreCase(align)) //$NON-NLS-1$
			{
				x = rect.x + rect.width - textWidth - 1;
				if (x < 1) {
					x = 1;
				}
			} else if ("center".equalsIgnoreCase(align)) //$NON-NLS-1$
			{
				int offset = (rect.width - textWidth) / 2;
				if (offset <= 0) {
					offset = 0;
				}
				x = x + offset + 1;
			}
		}
		return x;
	}
	
	private TextLayoutSupport()
	{
	    // no instantiation
	}
}
