/*******************************************************************************
 * Copyright (c) 2000, 2005 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.ui.internal.forms.widgets;

import java.text.BreakIterator;
import java.util.*;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;

/**
 * @version 1.0
 * @author
 */
public class TextSegment extends ParagraphSegment {
	private String colorId;

	private String fontId;

	private String text;

	protected boolean underline;

	private boolean wrapAllowed = true;

	protected Vector areaRectangles = new Vector();

	private TextFragment[] textFragments;

	class AreaRectangle {
		Rectangle rect;

		int from, to;

		public AreaRectangle(Rectangle rect, int from, int to) {
			this.rect = rect;
			this.from = from;
			this.to = to;
		}

		public boolean contains(int x, int y) {
			return rect.contains(x, y);
		}

		public boolean intersects(Rectangle region) {
			return rect.intersects(region);
		}

		public String getText() {
			if (from == 0 && to == -1)
				return TextSegment.this.getText();
			if (from > 0 && to == -1)
				return TextSegment.this.getText().substring(from);
			return TextSegment.this.getText().substring(from, to);
		}
	}

	static class SelectionRange {
		public int start;

		public int stop;

		public SelectionRange() {
			reset();
		}

		public void reset() {
			start = -1;
			stop = -1;
		}
	}

	static class TextFragment {
		short index;

		short length;

		public TextFragment(short index, short length) {
			this.index = index;
			this.length = length;
		}
	}

	public TextSegment(String text, String fontId) {
		this(text, fontId, null);
	}

	public TextSegment(String text, String fontId, String colorId) {
		this.text = cleanup(text);
		this.fontId = fontId;
		this.colorId = colorId;
	}

	private String cleanup(String text) {
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < text.length(); i++) {
			char c = text.charAt(i);
			if (c == '\n' || c == '\r' || c == '\f') {
				if (i > 0)
					buf.append(' ');
			} else
				buf.append(c);
		}
		return buf.toString();
	}

	public void setWordWrapAllowed(boolean value) {
		wrapAllowed = value;
	}

	public boolean isWordWrapAllowed() {
		return wrapAllowed;
	}

	public boolean isSelectable() {
		return false;
	}

	public String getColorId() {
		return colorId;
	}

	public String getText() {
		return text;
	}

	void setText(String text) {
		this.text = cleanup(text);
		textFragments = null;
	}

	void setColorId(String colorId) {
		this.colorId = colorId;
	}

	void setFontId(String fontId) {
		this.fontId = fontId;
		textFragments = null;
	}

	public boolean contains(int x, int y) {
		for (int i = 0; i < areaRectangles.size(); i++) {
			AreaRectangle ar = (AreaRectangle) areaRectangles.get(i);
			if (ar.contains(x, y))
				return true;
			if (i<areaRectangles.size()-1) {
				// test the gap
				Rectangle top = ar.rect;
				Rectangle bot = ((AreaRectangle)areaRectangles.get(i+1)).rect;
				if (y >= top.y+top.height && y < bot.y) {
					// in the gap
					int left = Math.max(top.x, bot.x);
					int right = Math.min(top.x+top.width, bot.x+bot.width);
					if (x>=left && x<=right) {
						return true;
					}
				}
			}
		}
		return false;
	}

	public boolean intersects(Rectangle rect) {
		for (int i = 0; i < areaRectangles.size(); i++) {
			AreaRectangle ar = (AreaRectangle) areaRectangles.get(i);
			if (ar.intersects(rect))
				return true;
			if (i<areaRectangles.size()-1) {
				// test the gap
				Rectangle top = ar.rect;
				Rectangle bot = ((AreaRectangle)areaRectangles.get(i+1)).rect;
				if (top.y+top.height < bot.y) {
					int y = top.y+top.height;
					int height = bot.y-y;
					int left = Math.max(top.x, bot.x);
					int right = Math.min(top.x+top.width, bot.x+bot.width);
					Rectangle gap = new Rectangle(left, y, right-left, height);
					if (gap.intersects(rect))
						return true;
				}
			}
		}
		return false;
	}

	public Rectangle getBounds() {
		int x = 0, y = 0;
		int width = 0, height = 0;

		for (int i = 0; i < areaRectangles.size(); i++) {
			AreaRectangle ar = (AreaRectangle) areaRectangles.get(i);
			if (i == 0) {
				x = ar.rect.x;
				y = ar.rect.y;
			} else
				x = Math.min(ar.rect.x, x);
			width = Math.max(ar.rect.width, width);
			height += ar.rect.height;
		}
		return new Rectangle(x, y, width, height);
	}

	public boolean advanceLocator(GC gc, int wHint, Locator locator,
			Hashtable objectTable, boolean computeHeightOnly) {
		Font oldFont = null;
		if (fontId != null) {
			oldFont = gc.getFont();
			Font newFont = (Font) objectTable.get(fontId);
			if (newFont != null)
				gc.setFont(newFont);
		}
		FontMetrics fm = gc.getFontMetrics();
		int lineHeight = fm.getHeight();
		boolean newLine = false;

		if (wHint == SWT.DEFAULT || !wrapAllowed) {
			Point extent = gc.textExtent(text);
			int totalExtent = locator.x+extent.x;
			if (isSelectable())
				totalExtent+=1;

			if (wHint != SWT.DEFAULT && totalExtent > wHint) {
				// new line
				locator.x = locator.indent;
				locator.y += locator.rowHeight;
				if (computeHeightOnly)
					locator.collectHeights();
				locator.rowHeight = 0;
				locator.leading = 0;
				newLine = true;
			}
			int width = extent.x;
			if (isSelectable())
				width += 1;
			locator.x += width;
			locator.width = locator.indent + width;
			locator.rowHeight = Math.max(locator.rowHeight, extent.y);
			locator.leading = Math.max(locator.leading, fm.getLeading());
			return newLine;
		}

		computeTextFragments(gc);

		int width = 0;
		Point lineExtent = new Point(0, 0);

		for (int i = 0; i < textFragments.length; i++) {
			TextFragment textFragment = textFragments[i];
			int currentExtent = locator.x + lineExtent.x;
			
			if (isSelectable())
				currentExtent += 1;
			
			if (currentExtent + textFragment.length > wHint) {
				// overflow
				int lineWidth = currentExtent;
				locator.rowHeight = Math.max(locator.rowHeight, lineExtent.y);
				locator.leading = Math.max(locator.leading, fm.getLeading());
				if (computeHeightOnly)
					locator.collectHeights();
				locator.x = locator.indent;
				locator.y += locator.rowHeight;
				locator.rowHeight = 0;
				locator.leading = 0;
				lineExtent.x = 0;
				lineExtent.y = 0;
				width = Math.max(width, lineWidth);
				newLine = true;
			}
			lineExtent.x += textFragment.length;
			lineExtent.y = Math.max(lineHeight, lineExtent.y);
		}
		int lineWidth = lineExtent.x;
		if (isSelectable())
			lineWidth += 1;
		locator.x += lineWidth;
		locator.width = width;
		locator.rowHeight = Math.max(locator.rowHeight, lineExtent.y);
		locator.leading = Math.max(locator.leading, fm.getLeading());
		if (oldFont != null) {
			gc.setFont(oldFont);
		}
		return newLine;
	}

	/**
	 * @param gc
	 * @param width
	 * @param locator
	 * @param selected
	 * @param selData
	 * @param color
	 * @param fm
	 * @param lineHeight
	 * @param descent
	 */
	private void layoutWithoutWrapping(GC gc, int width, Locator locator,
			boolean selected, FontMetrics fm, int lineHeight, int descent) {
		Point extent = gc.textExtent(text);
		int ewidth = extent.x;
		if (isSelectable())
			ewidth += 1;
		if (locator.x + ewidth > width-locator.marginWidth) {
			// new line
			locator.resetCaret();
			locator.y += locator.rowHeight;
			locator.rowHeight = 0;
			locator.rowCounter++;
		}
		int ly = locator.getBaseline(fm.getHeight() - fm.getLeading());
		//int lineY = ly + lineHeight - descent + 1;
		Rectangle br = new Rectangle(locator.x, ly, ewidth,
				lineHeight - descent + 3);
		areaRectangles.add(new AreaRectangle(br, 0, -1));
		locator.x += ewidth;
		locator.width = ewidth;
		locator.rowHeight = Math.max(locator.rowHeight, extent.y);
	}

	protected int convertOffsetToStringIndex(GC gc, String s, int x,
			int swidth, int selOffset) {
		int index = s.length();
		while (index > 0 && x + swidth > selOffset) {
			index--;
			String ss = s.substring(0, index);
			swidth = gc.textExtent(ss).x;
		}
		return index;
	}

	public void paintFocus(GC gc, Color bg, Color fg, boolean selected,
			Rectangle repaintRegion) {
		if (areaRectangles == null)
			return;
		for (int i = 0; i < areaRectangles.size(); i++) {
			AreaRectangle areaRectangle = (AreaRectangle) areaRectangles.get(i);
			Rectangle br = areaRectangle.rect;
			int bx = br.x;
			int by = br.y;
			if (repaintRegion != null) {
				bx -= repaintRegion.x;
				by -= repaintRegion.y;
			}
			if (selected) {
				gc.setBackground(bg);
				gc.setForeground(fg);
				gc.drawFocus(bx, by, br.width, br.height);
			} else {
				gc.setForeground(bg);
				gc.drawRectangle(bx, by, br.width - 1, br.height - 1);
			}
		}
	}

	public void paint(GC gc, boolean hover, Hashtable resourceTable,
			boolean selected, SelectionData selData, Rectangle repaintRegion) {
		this.paint(gc, hover, resourceTable, selected, false, selData,
				repaintRegion);
	}

	protected void paint(GC gc, boolean hover, Hashtable resourceTable,
			boolean selected, boolean rollover, SelectionData selData,
			Rectangle repaintRegion) {
		Font oldFont = null;
		Color oldColor = null;
		Color oldBg = null;

		// apply segment-specific font, color and background
		if (fontId != null) {
			oldFont = gc.getFont();
			Font newFont = (Font) resourceTable.get(fontId);
			if (newFont != null)
				gc.setFont(newFont);
		}
		if (!hover && colorId != null) {
			oldColor = gc.getForeground();
			Color newColor = (Color) resourceTable.get(colorId);
			if (newColor != null)
				gc.setForeground(newColor);
		}
		oldBg = gc.getBackground();

		FontMetrics fm = gc.getFontMetrics();
		int lineHeight = fm.getHeight();
		int descent = fm.getDescent();

		// paint area rectangles of the segment
		for (int i = 0; i < areaRectangles.size(); i++) {
			AreaRectangle areaRectangle = (AreaRectangle) areaRectangles.get(i);
			Rectangle rect = areaRectangle.rect;
			String text = areaRectangle.getText();
			Point extent = gc.textExtent(text);
			int textX = rect.x + (isSelectable()?1:0);
			int lineY = rect.y + lineHeight - descent + 1;
			paintString(gc, text, extent.x, textX, rect.y, lineY, selData,
					rect, hover, rollover, repaintRegion);
			if (selected) {
				int fx = rect.x;
				int fy = rect.y;
				if (repaintRegion != null) {
					fx -= repaintRegion.x;
					fy -= repaintRegion.y;
				}
				//To avoid partially cancelling the focus by painting over
				//X-ORed pixels, first cancel it yourself
				Color fg = gc.getForeground();
				gc.setForeground(oldBg);
				gc.drawRectangle(fx, fy, rect.width - 1, rect.height - 1);
				gc.setForeground(fg);
				gc.drawFocus(fx, fy, rect.width, rect.height);
			}
		}
		// restore GC resources
		if (oldFont != null) {
			gc.setFont(oldFont);
		}
		if (oldColor != null) {
			gc.setForeground(oldColor);
		}
		if (oldBg != null) {
			gc.setBackground(oldBg);
		}
	}

	public void computeSelection(GC gc, Hashtable resourceTable, SelectionData selData) {
		Font oldFont = null;

		if (fontId != null) {
			oldFont = gc.getFont();
			Font newFont = (Font) resourceTable.get(fontId);
			if (newFont != null)
				gc.setFont(newFont);
		}

		for (int i = 0; i < areaRectangles.size(); i++) {
			AreaRectangle areaRectangle = (AreaRectangle) areaRectangles.get(i);
			Rectangle rect = areaRectangle.rect;
			String text = areaRectangle.getText();
			Point extent = gc.textExtent(text);
			computeSelection(gc, text, extent.x, selData,
					rect);
		}
		// restore GC resources
		if (oldFont != null) {
			gc.setFont(oldFont);
		}
	}

	private void paintString(GC gc, String s, int swidth, int x, int y,
			int lineY, SelectionData selData, Rectangle bounds, boolean hover,
			boolean rolloverMode, Rectangle repaintRegion) {
		// repaints one area rectangle
		if (selData != null && selData.isEnclosed()) {
			Color savedBg = gc.getBackground();
			Color savedFg = gc.getForeground();
			int leftOffset = selData.getLeftOffset(bounds.height);
			int rightOffset = selData.getRightOffset(bounds.height);
			boolean firstRow = selData.isFirstSelectionRow(bounds.y,
					bounds.height);
			boolean lastRow = selData.isLastSelectionRow(bounds.y,
					bounds.height);
			boolean selectedRow = selData
					.isSelectedRow(bounds.y, bounds.height);

			int sstart = -1;
			int sstop = -1;

			if ((firstRow && x + swidth < leftOffset)
					|| (lastRow && x > rightOffset)) {
				paintStringSegment(gc, s, gc.textExtent(s).x, x, y, lineY,
						hover, rolloverMode, repaintRegion);
				return;
			}

			if (firstRow && bounds.x + swidth > leftOffset) {
				sstart = convertOffsetToStringIndex(gc, s, bounds.x, swidth,
						leftOffset);
			}
			if (lastRow && bounds.x + swidth > rightOffset) {
				sstop = convertOffsetToStringIndex(gc, s, bounds.x, swidth,
						rightOffset);
			}

			if (firstRow && sstart != -1) {
				String left = s.substring(0, sstart);
				int width = gc.textExtent(left).x;
				paintStringSegment(gc, left, width, x, y, lineY, hover,
						rolloverMode, repaintRegion);
				x += width;
			}
			if (selectedRow) {
				int lindex = sstart != -1 ? sstart : 0;
				int rindex = sstop != -1 ? sstop : s.length();
				String mid = s.substring(lindex, rindex);
				Point extent = gc.textExtent(mid);
				gc.setForeground(selData.fg);
				gc.setBackground(selData.bg);
				gc.fillRectangle(x, y, extent.x, extent.y);
				paintStringSegment(gc, mid, extent.x, x, y, lineY, hover,
						rolloverMode, repaintRegion);
				x += extent.x;
				gc.setForeground(savedFg);
				gc.setBackground(savedBg);
			} else {
				paintStringSegment(gc, s, gc.textExtent(s).x, x, y, lineY,
						hover, rolloverMode, repaintRegion);
			}
			if (lastRow && sstop != -1) {
				String right = s.substring(sstop);
				paintStringSegment(gc, right, gc.textExtent(right).x, x, y,
						lineY, hover, rolloverMode, repaintRegion);
			}
		} else {
			paintStringSegment(gc, s, gc.textExtent(s).x, x, y, lineY, hover,
					rolloverMode, repaintRegion);
		}
	}

	private void computeSelection(GC gc, String s, int swidth, SelectionData selData, Rectangle bounds) {
		int leftOffset = selData.getLeftOffset(bounds.height);
		int rightOffset = selData.getRightOffset(bounds.height);
		boolean firstRow = selData.isFirstSelectionRow(bounds.y, bounds.height);
		boolean lastRow = selData.isLastSelectionRow(bounds.y, bounds.height);
		boolean selectedRow = selData.isSelectedRow(bounds.y, bounds.height);

		int sstart = -1;
		int sstop = -1;

		if (firstRow && bounds.x + swidth > leftOffset) {
			sstart = convertOffsetToStringIndex(gc, s, bounds.x, swidth,
					leftOffset);
		}
		if (lastRow && bounds.x + swidth > rightOffset) {
			sstop = convertOffsetToStringIndex(gc, s, bounds.x, swidth,
					rightOffset);
		}

		if (selectedRow) {
			int lindex = sstart != -1 ? sstart : 0;
			int rindex = sstop != -1 ? sstop : s.length();
			String mid = s.substring(lindex, rindex);
			selData.addSegment(mid);
		}
	}

	/**
	 * @param gc
	 * @param s
	 * @param x
	 * @param y
	 * @param lineY
	 * @param hover
	 * @param rolloverMode
	 */
	private void paintStringSegment(GC gc, String s, int swidth, int x, int y,
			int lineY, boolean hover, boolean rolloverMode,
			Rectangle repaintRegion) {
		boolean reverse = false;
		int clipX = x;
		int clipY = y;
		int clipLineY = lineY;
		if (repaintRegion != null) {
			clipX -= repaintRegion.x;
			clipY -= repaintRegion.y;
			clipLineY -= repaintRegion.y;
		}
		if (underline || hover || rolloverMode) {
			if (rolloverMode && !hover)
				reverse = true;
		}
		if (reverse) {
			drawUnderline(gc, swidth, clipX, clipLineY, hover, rolloverMode);
			gc.drawString(s, clipX, clipY, false);
		} else {
			gc.drawString(s, clipX, clipY, false);
			drawUnderline(gc, swidth, clipX, clipLineY, hover, rolloverMode);
		}
	}

	private void drawUnderline(GC gc, int swidth, int x, int y, boolean hover,
			boolean rolloverMode) {
		if (underline || hover || rolloverMode) {
			Color saved = null;
			if (rolloverMode && !hover) {
				saved = gc.getForeground();
				gc.setForeground(gc.getBackground());
			}
			gc.drawLine(x, y, x + swidth-1, y);
			if (saved != null)
				gc.setForeground(saved);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.internal.forms.widgets.ParagraphSegment#layout(org.eclipse.swt.graphics.GC,
	 *      int, org.eclipse.ui.internal.forms.widgets.Locator,
	 *      java.util.Hashtable, boolean,
	 *      org.eclipse.ui.internal.forms.widgets.SelectionData)
	 */
	public void layout(GC gc, int width, Locator locator,
			Hashtable resourceTable, boolean selected) {
		Font oldFont = null;

		areaRectangles.clear();

		if (fontId != null) {
			oldFont = gc.getFont();
			Font newFont = (Font) resourceTable.get(fontId);
			if (newFont != null)
				gc.setFont(newFont);
		}
		FontMetrics fm = gc.getFontMetrics();
		int lineHeight = fm.getHeight();
		int descent = fm.getDescent();

		if (!wrapAllowed) {
			layoutWithoutWrapping(gc, width, locator, selected, fm, lineHeight,
					descent);
		} else {
			int lineStart = 0;
			int lastLoc = 0;
			Point lineExtent = new Point(0, 0);
			computeTextFragments(gc);
			int rightEdge = width-locator.marginWidth;
			for (int i = 0; i < textFragments.length; i++) {
				TextFragment fragment = textFragments[i];
				int breakLoc = fragment.index;
				if (breakLoc == 0)
					continue;
				if (locator.x + lineExtent.x + fragment.length > rightEdge) {
					// overflow
					int lineWidth = locator.x + lineExtent.x;
					if (isSelectable())
						lineWidth += 1;
					int ly = locator.getBaseline(lineHeight - fm.getLeading());
					Rectangle br = new Rectangle(isSelectable()?
							locator.x - 1:locator.x, ly,
							isSelectable()?lineExtent.x + 1:lineExtent.x, lineHeight - descent + 3);
					areaRectangles
							.add(new AreaRectangle(br, lineStart, lastLoc));

					locator.rowHeight = Math.max(locator.rowHeight,
							lineExtent.y);
					locator.resetCaret();
					if (isSelectable())
						locator.x += 1;					
					locator.y += locator.rowHeight;
					locator.rowCounter++;
					locator.rowHeight = 0;
					lineStart = lastLoc;
					lineExtent.x = 0;
					lineExtent.y = 0;
				}
				lastLoc = breakLoc;
				lineExtent.x += fragment.length;
				lineExtent.y = Math.max(lineHeight, lineExtent.y);
			}
			//String lastLine = text.substring(lineStart, lastLoc);
			int ly = locator.getBaseline(lineHeight - fm.getLeading());
			int lastWidth = lineExtent.x;
			if (isSelectable())
				lastWidth += 1;
			Rectangle br = new Rectangle(isSelectable()?locator.x - 1:locator.x, ly, 
					isSelectable()?lineExtent.x + 1:lineExtent.x,
					lineHeight - descent + 3);
			//int lineY = ly + lineHeight - descent + 1;
			areaRectangles.add(new AreaRectangle(br, lineStart, lastLoc));
			locator.x += lastWidth;
			locator.rowHeight = Math.max(locator.rowHeight, lineExtent.y);
		}
		if (oldFont != null) {
			gc.setFont(oldFont);
		}
	}

	private void computeTextFragments(GC gc) {
		if (textFragments != null)
			return;
		ArrayList list = new ArrayList();
		BreakIterator wb = BreakIterator.getLineInstance();
		wb.setText(getText());
		int cursor = 0;
		for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) {
			if (loc == 0)
				continue;
			String word = text.substring(cursor, loc);
			Point extent = gc.textExtent(word);
			list.add(new TextFragment((short) loc, (short) extent.x));
			cursor = loc;
		}
		textFragments = (TextFragment[]) list.toArray(new TextFragment[list
				.size()]);
	}
	
	public void clearCache(String fontId) {
		if (fontId==null && this.fontId==null)
			textFragments = null;
		else if (fontId!=null && this.fontId!=null && fontId.equals(this.fontId))
			textFragments = null;
	}
}
