/*******************************************************************************
 * Copyright (c) 2000, 2010 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 API and implementation
 *******************************************************************************/
package org.eclipse.draw2d.text;

import java.util.List;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.TextLayout;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.TextUtilities;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.rap.swt.SWT;

/**
 * An inline flow figure that renders a string of text across one or more lines.
 * A TextFlow cannot contain children. All <code>InlineFlow</code> figure's must
 * be parented by a <code>FlowFigure</code>.
 * <p>
 * WARNING: This class is not intended to be subclassed by clients.
 * 
 * @author hudsonr
 * @author Pratik Shah
 * @since 2.1
 */
public class TextFlow extends InlineFlow {

	static final String ELLIPSIS = "..."; //$NON-NLS-1$
	private BidiInfo bidiInfo;
	private int selectionEnd = -1;
	private String text;

	/**
	 * Constructs a new TextFlow with the empty String.
	 * 
	 * @see java.lang.Object#Object()
	 */
	public TextFlow() {
		this(new String());
	}

	/**
	 * Constructs a new TextFlow with the specified String.
	 * 
	 * @param s
	 *            the string
	 */
	public TextFlow(String s) {
		text = s;
	}

	/**
	 * Returns the width of the text until the first line-break.
	 * 
	 * @see org.eclipse.draw2d.text.FlowFigure#addLeadingWordRequirements(int[])
	 */
	public boolean addLeadingWordRequirements(int[] width) {
		return addLeadingWordWidth(getText(), width);
	}

	/**
	 * Calculates the width taken up by the given text before a line-break is
	 * encountered.
	 * 
	 * @param text
	 *            the text in which the break is to be found
	 * @param width
	 *            the width before the next line-break (if one's found; the
	 *            width of all the given text, otherwise) will be added on to
	 *            the first int in the given array
	 * @return <code>true</code> if a line-break was found
	 * @since 3.1
	 */
	boolean addLeadingWordWidth(String text, int[] width) {
		if (text.length() == 0)
			return false;
		if (Character.isWhitespace(text.charAt(0)))
			return true;

		text = 'a' + text + 'a';
		FlowUtilities.LINE_BREAK.setText(text);
		int index = FlowUtilities.LINE_BREAK.next() - 1;
		if (index == 0)
			return true;
		while (Character.isWhitespace(text.charAt(index)))
			index--;
		boolean result = index < text.length() - 1;
		// index should point to the end of the actual text (not including the
		// 'a' that was
		// appended), if there were no breaks
		if (index == text.length() - 1)
			index--;
		text = text.substring(1, index + 1);

		if (bidiInfo == null)
			width[0] += getTextUtilities().getTextExtents(text, getFont()).width;
		else {
			TextLayout textLayout = FlowUtilities.getTextLayout();
			textLayout.setFont(getFont());
			textLayout.setText(text);
			width[0] += textLayout.getBounds().width;
		}
		return result;
	}

	/**
	 * A TextFlow contributes its text.
	 * 
	 * @see org.eclipse.draw2d.text.FlowFigure#contributeBidi(org.eclipse.draw2d.text.BidiProcessor)
	 */
	protected void contributeBidi(BidiProcessor proc) {
		bidiInfo = null;
		proc.add(this, getText());
	}

	/**
	 * @see org.eclipse.draw2d.text.InlineFlow#createDefaultFlowLayout()
	 */
	protected FlowFigureLayout createDefaultFlowLayout() {
		return new ParagraphTextLayout(this);
	}

	private int findNextLineOffset(Point p, int[] trailing) {
		if (getBounds().bottom() <= p.y)
			return -1;

		TextFragmentBox closestBox = null;
		int index = 0;
		List fragments = getFragmentsWithoutBorder();
		for (int i = fragments.size() - 1; i >= 0; i--) {
			TextFragmentBox box = (TextFragmentBox) fragments.get(i);
			if (box.getBaseline() - box.getLineRoot().getAscent() > p.y
					&& (closestBox == null
							|| box.getBaseline() < closestBox.getBaseline() || (box
							.getBaseline() == closestBox.getBaseline() && hDistanceBetween(
							box, p.x) < hDistanceBetween(closestBox, p.x)))) {
				closestBox = box;
				index = i;
			}
		}
		return findOffset(p, trailing, closestBox, index);
	}

	private int findOffset(Point p, int[] trailing, TextFragmentBox box,
			int boxIndex) {
		if (box == null)
			return -1;
		TextLayout layout = FlowUtilities.getTextLayout();
		layout.setFont(getFont());
		layout.setText(getBidiSubstring(box, boxIndex));
		int x = p.x - box.getX();
		if (isMirrored())
			x = box.getWidth() - x;
		int layoutOffset = layout
				.getOffset(x, p.y - box.getTextTop(), trailing);
		return box.offset + layoutOffset - getBidiPrefixLength(box, boxIndex);
	}

	private int findPreviousLineOffset(Point p, int[] trailing) {
		if (getBounds().y > p.y)
			return -1;

		TextFragmentBox closestBox = null;
		int index = 0;
		List fragments = getFragmentsWithoutBorder();
		for (int i = fragments.size() - 1; i >= 0; i--) {
			TextFragmentBox box = (TextFragmentBox) fragments.get(i);
			if (box.getBaseline() + box.getLineRoot().getDescent() < p.y
					&& (closestBox == null
							|| box.getBaseline() > closestBox.getBaseline() || (box
							.getBaseline() == closestBox.getBaseline() && hDistanceBetween(
							box, p.x) < hDistanceBetween(closestBox, p.x)))) {
				closestBox = box;
				index = i;
			}
		}
		return findOffset(p, trailing, closestBox, index);
	}

	int getAscent() {
		return getTextUtilities().getAscent(getFont());
	}

	/**
	 * Returns the BidiInfo for this figure or <code>null</code>.
	 * 
	 * @return <code>null</code> or the info
	 * @since 3.1
	 */
	public BidiInfo getBidiInfo() {
		return bidiInfo;
	}

	private int getBidiPrefixLength(TextFragmentBox box, int index) {
		if (box.getBidiLevel() < 1)
			return 0;
		if (index > 0 || !bidiInfo.leadingJoiner)
			return 1;
		return 2;
	}

	/**
	 * @param box
	 *            which fragment
	 * @param index
	 *            the fragment index
	 * @return the bidi string for that fragment
	 * @since 3.1
	 */
	protected String getBidiSubstring(TextFragmentBox box, int index) {
		if (box.getBidiLevel() < 1)
			return getText().substring(box.offset, box.offset + box.length);

		StringBuffer buffer = new StringBuffer(box.length + 3);
		buffer.append(box.isRightToLeft() ? BidiChars.RLO : BidiChars.LRO);
		if (index == 0 && bidiInfo.leadingJoiner)
			buffer.append(BidiChars.ZWJ);
		buffer.append(getText().substring(box.offset, box.offset + box.length));
		if (index == getFragmentsWithoutBorder().size() - 1
				&& bidiInfo.trailingJoiner)
			buffer.append(BidiChars.ZWJ);
		return buffer.toString();
	}

	/**
	 * Returns the CaretInfo in absolute coordinates. The offset must be between
	 * 0 and the length of the String being displayed.
	 * 
	 * @since 3.1
	 * @param offset
	 *            the location in this figure's text
	 * @param trailing
	 *            true if the caret is being placed after the offset
	 * @exception IllegalArgumentException
	 *                If the offset is not between <code>0</code> and the length
	 *                of the string inclusively
	 * @return the caret bounds relative to this figure
	 */
	public CaretInfo getCaretPlacement(int offset, boolean trailing) {
		if (offset < 0 || offset > getText().length())
			throw new IllegalArgumentException("Offset: " + offset //$NON-NLS-1$
					+ " is invalid"); //$NON-NLS-1$

		if (offset == getText().length())
			trailing = false;

		List fragments = getFragmentsWithoutBorder();
		int i = fragments.size();
		TextFragmentBox box;
		do
			box = (TextFragmentBox) fragments.get(--i);
		while (offset < box.offset && i > 0);

		// Cannot be trailing and after the last char, so go to first char in
		// next box
		if (trailing && box.offset + box.length <= offset) {
			box = (TextFragmentBox) fragments.get(++i);
			offset = box.offset;
			trailing = false;
		}

		Point where = getPointInBox(box, offset, i, trailing);
		CaretInfo info = new CaretInfo(where.x, where.y, box.getAscent(),
				box.getDescent(), box.getLineRoot().getAscent(), box
						.getLineRoot().getDescent());
		translateToAbsolute(info);
		return info;
	}

	Point getPointInBox(TextFragmentBox box, int offset, int index,
			boolean trailing) {
		offset -= box.offset;
		offset = Math.min(box.length, offset);
		Point result = new Point(0, box.getTextTop());
		if (bidiInfo == null) {
			if (trailing && offset < box.length)
				offset++;
			String substring = getText().substring(box.offset,
					box.offset + offset);
			result.x = getTextUtilities().getTextExtents(substring, getFont()).width;
		} else {
			TextLayout layout = FlowUtilities.getTextLayout();
			layout.setFont(getFont());
			String fragString = getBidiSubstring(box, index);
			layout.setText(fragString);
			offset += getBidiPrefixLength(box, index);
			result.x = layout.getLocation(offset, trailing).x;
			if (isMirrored())
				result.x = box.width - result.x;
		}
		result.x += box.getX();
		return result;
	}

	int getDescent() {
		return getTextUtilities().getDescent(getFont());
	}

	/**
	 * Returns the minimum character offset which is on the given baseline
	 * y-coordinate. The y location should be relative to this figure. The
	 * return value will be between 0 and N-1. If no fragment is located on the
	 * baseline, <code>-1</code> is returned.
	 * 
	 * @since 3.1
	 * @param baseline
	 *            the relative baseline coordinate
	 * @return -1 or the lowest offset for the line
	 */
	public int getFirstOffsetForLine(int baseline) {
		TextFragmentBox box;
		List fragments = getFragmentsWithoutBorder();
		for (int i = 0; i < fragments.size(); i++) {
			box = (TextFragmentBox) fragments.get(i);
			if (baseline == box.getBaseline())
				return box.offset;
		}
		return -1;
	}

	/**
	 * Returns the <code>TextFragmentBox</code> fragments contained in this
	 * TextFlow, not including the border fragments. The returned list should
	 * not be modified.
	 * 
	 * @return list of fragments without the border fragments
	 * @since 3.4
	 */
	protected List getFragmentsWithoutBorder() {
		List fragments = getFragments();
		if (getBorder() != null)
			fragments = fragments.subList(1, fragments.size() - 1);
		return fragments;
	}

	/**
	 * Returns the maximum offset for a character which is on the given baseline
	 * y-coordinate. The y location should be relative to this figure. The
	 * return value will be between 0 and N-1. If no fragment is located on the
	 * baseline, <code>-1</code> is returned.
	 * 
	 * @since 3.1
	 * @param baseline
	 *            the relative baseline coordinate
	 * @return -1 or the highest offset at the given baseline
	 */
	public int getLastOffsetForLine(int baseline) {
		TextFragmentBox box;
		List fragments = getFragmentsWithoutBorder();
		for (int i = fragments.size() - 1; i >= 0; i--) {
			box = (TextFragmentBox) fragments.get(i);
			if (baseline == box.getBaseline())
				return box.offset + box.length - 1;
		}
		return -1;
	}

	/**
	 * Returns the offset nearest the given point either up or down one line. If
	 * no offset is found, -1 is returned. <code>trailing[0]</code> will be set
	 * to 1 if the reference point is closer to the trailing edge of the offset
	 * than it is to the leading edge.
	 * 
	 * @since 3.1
	 * @param p
	 *            a reference point
	 * @param down
	 *            <code>true</code> if the search is down
	 * @param trailing
	 *            an int array
	 * @return the next offset or <code>-1</code>
	 */
	public int getNextOffset(Point p, boolean down, int[] trailing) {
		return down ? findNextLineOffset(p, trailing) : findPreviousLineOffset(
				p, trailing);
	}

	/**
	 * Returns the next offset which is visible in at least one fragment or -1
	 * if there is not one. A visible offset means that the character or the one
	 * preceding it is displayed, which implies that a caret can be positioned
	 * at such an offset. This is useful for advancing a caret past characters
	 * which resulted in a line wrap.
	 * 
	 * @param offset
	 *            the reference offset
	 * @return the next offset which is visible
	 * @since 3.1
	 */
	public int getNextVisibleOffset(int offset) {
		TextFragmentBox box;
		List fragments = getFragmentsWithoutBorder();
		for (int i = 0; i < fragments.size(); i++) {
			box = (TextFragmentBox) fragments.get(i);
			if (box.offset + box.length <= offset)
				continue;
			return Math.max(box.offset, offset + 1);
		}
		return -1;
	}

	/**
	 * Returns the offset of the character directly below or nearest the given
	 * location. The point must be relative to this figure. The return value
	 * will be between 0 and N-1. If the proximity argument is not
	 * <code>null</code>, the result may also be <code>-1</code> if no offset
	 * was found within the proximity.
	 * <P>
	 * For a typical character, the trailing argument will be filled in to
	 * indicate whether the point is closer to the leading edge (0) or the
	 * trailing edge (1). When the point is over a cluster composed of multiple
	 * characters, the trailing argument will be filled with the position of the
	 * character in the cluster that is closest to the point.
	 * <P>
	 * If the proximity argument is not <code>null</code>, then the location may
	 * be no further than the proximity given. Passing <code>null</code> is
	 * equivalent to passing <code>new
	 * Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)</code>. The
	 * <code>width</code> field of the proximity will contain the horizontal
	 * distance, <code>height</code> will contain vertical. Vertical proximity
	 * is more important than horizontal. The returned offset is the lowest
	 * index with minimum vertical proximity not exceeding the given limit, with
	 * horizontal proximity not exceeding the given limit. If an offset that is
	 * within the proximity is found, then the given <code>Dimension</code> will
	 * be updated to reflect the new proximity.
	 * 
	 * 
	 * @since 3.1
	 * @param p
	 *            the point relative to this figure
	 * @param trailing
	 *            the trailing buffer
	 * @param proximity
	 *            restricts and records the distance of the returned offset
	 * @return the nearest offset in this figure's text
	 */
	public int getOffset(Point p, int trailing[], Dimension proximity) {
		if (proximity == null)
			proximity = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
		TextFragmentBox closestBox = null;
		int index = 0;
		int dy;
		int dx;
		int i = 0;
		int size = fragments.size();
		if (getBorder() instanceof FlowBorder) {
			i++;
			size--;
		}
		for (; i < size; i++) {
			TextFragmentBox box = (TextFragmentBox) fragments.get(i);
			dy = vDistanceBetween(box, p.y);
			if (dy > proximity.height)
				continue;
			dx = hDistanceBetween(box, p.x);
			if (dy == proximity.height && dx >= proximity.width)
				continue;
			proximity.height = dy;
			proximity.width = dx;
			closestBox = box;
			index = i;
		}
		return findOffset(p, trailing, closestBox, index);
	}

	/**
	 * Returns the previous offset which is visible in at least one fragment or
	 * -1 if there is not one. See {@link #getNextVisibleOffset(int)} for more.
	 * 
	 * @param offset
	 *            a reference offset
	 * @return -1 or the previous offset which is visible
	 * @since 3.1
	 */

	public int getPreviousVisibleOffset(int offset) {
		TextFragmentBox box;
		if (offset == -1)
			offset = Integer.MAX_VALUE;
		List fragments = getFragmentsWithoutBorder();
		for (int i = fragments.size() - 1; i >= 0; i--) {
			box = (TextFragmentBox) fragments.get(i);
			if (box.offset >= offset)
				continue;
			return Math.min(box.offset + box.length, offset - 1);
		}
		return -1;
	}

	/**
	 * @return the String being displayed; will not be <code>null</code>
	 */
	public String getText() {
		return text;
	}

	int getVisibleAscent() {
		if (getBorder() instanceof FlowBorder) {
			FlowBorder border = (FlowBorder) getBorder();
			return border.getInsets(this).top + getAscent();
		}
		return getAscent();
	}

	int getVisibleDescent() {
		if (getBorder() instanceof FlowBorder) {
			FlowBorder border = (FlowBorder) getBorder();
			return border.getInsets(this).bottom + getDescent();
		}
		return getDescent();
	}

	private int hDistanceBetween(TextFragmentBox box, int x) {
		if (x < box.getX())
			return box.getX() - x;
		return Math.max(0, x - (box.getX() + box.getWidth()));
	}

	/**
	 * Returns <code>true</code> if a portion if the text is truncated using
	 * ellipses ("...").
	 * 
	 * @return <code>true</code> if the text is truncated with ellipses
	 */
	public boolean isTextTruncated() {
		for (int i = 0; i < fragments.size(); i++) {
			if (((TextFragmentBox) fragments.get(i)).isTruncated())
				return true;
		}
		return false;
	}

	/**
	 * @see org.eclipse.draw2d.Figure#paintFigure(Graphics)
	 */
	protected void paintFigure(Graphics g) {
		TextFragmentBox frag;
		g.getClip(Rectangle.SINGLETON);
		int yStart = Rectangle.SINGLETON.y;
		int yEnd = Rectangle.SINGLETON.bottom();

		for (int i = 0; i < fragments.size(); i++) {
			frag = (TextFragmentBox) fragments.get(i);
			// g.drawLine(frag.getX(), frag.getLineRoot().getVisibleTop(),
			// frag.getWidth() + frag.getX(),
			// frag.getLineRoot().getVisibleTop());
			// g.drawLine(frag.getX(), frag.getBaseline(), frag.getWidth() +
			// frag.getX(), frag.getBaseline());
			if (frag.offset == -1)
				continue;
			// Loop until first visible fragment
			if (yStart > frag.getLineRoot().getVisibleBottom() + 1)// The + 1 is
																	// for
																	// disabled
																	// text
				continue;
			// Break loop at first non-visible fragment
			if (yEnd < frag.getLineRoot().getVisibleTop())
				break;

			String draw = getBidiSubstring(frag, i);

			if (frag.isTruncated())
				draw += ELLIPSIS;

			if (!isEnabled()) {
				Color fgColor = g.getForegroundColor();
				g.setForegroundColor(ColorConstants.buttonLightest);
				paintText(g, draw, frag.getX() + 1, frag.getBaseline()
						- getAscent() + 1, frag.getBidiLevel());
				g.setForegroundColor(ColorConstants.buttonDarker);
				paintText(g, draw, frag.getX(), frag.getBaseline()
						- getAscent(), frag.getBidiLevel());
				g.setForegroundColor(fgColor);
			} else {
				paintText(g, draw, frag.getX(), frag.getBaseline()
						- getAscent(), frag.getBidiLevel());
			}
		}
	}

	/**
	 * @see InlineFlow#paintSelection(org.eclipse.draw2d.Graphics)
	 */
	protected void paintSelection(Graphics graphics) {
		if (selectionStart == -1)
			return;
		graphics.setXORMode(true);
		graphics.setBackgroundColor(ColorConstants.white);

		TextFragmentBox frag;
		for (int i = 0; i < fragments.size(); i++) {
			frag = (TextFragmentBox) fragments.get(i);
			// Loop until first visible fragment
			if (frag.offset + frag.length <= selectionStart)
				continue;
			if (frag.offset > selectionEnd)
				return;
			if (selectionStart <= frag.offset
					&& selectionEnd >= frag.offset + frag.length) {
				int y = frag.getLineRoot().getVisibleTop();
				int height = frag.getLineRoot().getVisibleBottom() - y;
				graphics.fillRectangle(frag.getX(), y, frag.getWidth(), height);
			} else if (selectionEnd > frag.offset
					&& selectionStart < frag.offset + frag.length) {
				Point p1 = getPointInBox(frag,
						Math.max(frag.offset, selectionStart), i, false);
				Point p2 = getPointInBox(frag,
						Math.min(frag.offset + frag.length, selectionEnd) - 1,
						i, true);
				Rectangle rect = new Rectangle(p1, p2);
				rect.width--;
				rect.y = frag.getLineRoot().getVisibleTop();
				rect.height = frag.getLineRoot().getVisibleBottom() - rect.y;
				graphics.fillRectangle(rect);
			}
		}
	}

	protected void paintText(Graphics g, String draw, int x, int y,
			int bidiLevel) {
		if (bidiLevel == -1) {
			g.drawText(draw, x, y);
		} else {
			TextLayout tl = FlowUtilities.getTextLayout();
			if (isMirrored())
				tl.setOrientation(SWT.RIGHT_TO_LEFT);
			tl.setFont(g.getFont());
			tl.setText(draw);
			g.drawTextLayout(tl, x, y);
		}
	}

	/**
	 * @see org.eclipse.draw2d.text.FlowFigure#setBidiInfo(org.eclipse.draw2d.text.BidiInfo)
	 */
	public void setBidiInfo(BidiInfo info) {
		this.bidiInfo = info;
	}

	/**
	 * Sets the extent of selection. The selection range is inclusive. For
	 * example, the range [0, 0] indicates that the first character is selected.
	 * 
	 * @param start
	 *            the start offset
	 * @param end
	 *            the end offset
	 * @since 3.1
	 */
	public void setSelection(int start, int end) {
		boolean repaint = false;

		if (selectionStart == start) {
			if (selectionEnd == end)
				return;
			repaint = true;
		} else
			repaint = selectionStart != selectionEnd || start != end;

		selectionStart = start;
		selectionEnd = end;
		if (repaint)
			repaint();
	}

	/**
	 * Sets the text being displayed. The string may not be <code>null</code>.
	 * 
	 * @param s
	 *            The new text
	 */
	public void setText(String s) {
		if (s != null && !s.equals(text)) {
			text = s;
			revalidateBidi(this);
			repaint();
		}
	}

	/**
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return text;
	}

	private int vDistanceBetween(TextFragmentBox box, int y) {
		int top = box.getBaseline() - box.getLineRoot().getAscent();
		if (y < top)
			return top - y;
		return Math.max(0, y
				- (box.getBaseline() + box.getLineRoot().getDescent()));
	}

	/**
	 * Gets the <code>FlowUtilities</code> instance to be used in measurement
	 * calculations.
	 * 
	 * @return a <code>FlowUtilities</code> instance
	 * @since 3.4
	 */
	protected FlowUtilities getFlowUtilities() {
		return FlowUtilities.INSTANCE;
	}

	/**
	 * Gets the <code>TextUtilities</code> instance to be used in measurement
	 * calculations.
	 * 
	 * @return a <code>TextUtilities</code> instance
	 * @since 3.4
	 */
	protected TextUtilities getTextUtilities() {
		return TextUtilities.INSTANCE;
	}

}