/*******************************************************************************
 * 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).
	 */
	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);
		}
	}

	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;
	}

	public static void paintTextFigure(Graphics g, List fragments, Font font,
			int textDecoration) {
		paintTextFigure(g, fragments, font, null, 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);
		}
	}

	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$
		}
	}

	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;
	}
}
