/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.update.ui.forms.internal.engine;

import java.io.*;
import java.util.*;
import javax.xml.parsers.*;

import org.eclipse.core.runtime.*;
import org.eclipse.jface.resource.*;
import org.eclipse.update.ui.forms.internal.*;
import org.w3c.dom.*;
import org.xml.sax.*;

/**
 * @version 	1.0
 * @author
 */
public class TextModel implements ITextModel {
	private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

	Vector paragraphs;
	IHyperlinkListener urlListener;
	IHyperlinkSegment[] hyperlinks;
	int selectedLinkIndex = -1;
	HyperlinkSettings hyperlinkSettings;
	
	public TextModel() {
		reset();
	}

	class LocalHyperlinkSettings extends HyperlinkSettings {
	}

	/*
	 * @see ITextModel#getParagraphs()
	 */
	public IParagraph[] getParagraphs() {
		if (paragraphs == null)
			return new IParagraph[0];
		return (IParagraph[]) paragraphs.toArray(
			new IParagraph[paragraphs.size()]);
	}
	
	public String getAccessibleText() {
		if (paragraphs == null)
			return "";
		StringBuffer sbuf = new StringBuffer();
		for (int i=0; i<paragraphs.size(); i++) {
			IParagraph paragraph  = (IParagraph)paragraphs.get(i);
			String text = paragraph.getAccessibleText();
			sbuf.append(text);
		}
		return sbuf.toString();
	}

	/*
	 * @see ITextModel#parse(String)
	 */
	public void parseTaggedText(String taggedText, boolean expandURLs)
		throws CoreException {
		if (taggedText==null) {
			reset();
			return;
		}
		try {
			InputStream stream =
				new ByteArrayInputStream(taggedText.getBytes("UTF8"));
			parseInputStream(stream, expandURLs);
		} catch (UnsupportedEncodingException e) {
		}
	}

	public void parseInputStream(InputStream is, boolean expandURLs)
		throws CoreException {
			
		documentBuilderFactory.setNamespaceAware(true);
	
		reset();
		try {
			DocumentBuilder parser = documentBuilderFactory.newDocumentBuilder();
			InputSource source = new InputSource(is);
			Document doc = parser.parse(source);
			processDocument(doc, expandURLs);
		} catch (ParserConfigurationException e) {
			FormsPlugin.logException(e);
		} catch (SAXException e) {
			FormsPlugin.logException(e);
		} catch (IOException e) {
			FormsPlugin.logException(e);
		}
	}

	private void processDocument(Document doc, boolean expandURLs) {
		Node root = doc.getDocumentElement();
		NodeList children = root.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			if (child.getNodeType() == Node.TEXT_NODE) {
				// Make an implicit paragraph
				String text = child.getNodeValue();
				if (text != null && !isIgnorableWhiteSpace(text, true)) {
					Paragraph p = new Paragraph(true);
					p.parseRegularText(
						text,
						expandURLs,
						getHyperlinkSettings(),
						null);
					paragraphs.add(p);
				}
			} else if (child.getNodeType() == Node.ELEMENT_NODE) {
				String tag = child.getNodeName().toLowerCase();
				if (tag.equals("p")) {
					IParagraph p = processParagraph(child, expandURLs);
					if (p != null)
						paragraphs.add(p);
				} else if (tag.equals("li")) {
					IParagraph p = processListItem(child, expandURLs);
					if (p != null)
						paragraphs.add(p);
				}
			}
		}
	}
	private IParagraph processParagraph(Node paragraph, boolean expandURLs) {
		NodeList children = paragraph.getChildNodes();
		NamedNodeMap atts = paragraph.getAttributes();
		Node addSpaceAtt = atts.getNamedItem("addVerticalSpace");
		boolean addSpace = true;

		if (addSpaceAtt != null) {
			String value = addSpaceAtt.getNodeValue();
			addSpace = value.equalsIgnoreCase("true");
		}
		Paragraph p = new Paragraph(addSpace);

		processSegments(p, children, expandURLs);
		return p;
	}
	private IParagraph processListItem(Node listItem, boolean expandURLs) {
		NodeList children = listItem.getChildNodes();
		NamedNodeMap atts = listItem.getAttributes();
		Node addSpaceAtt = atts.getNamedItem("addVerticalSpace");
		Node styleAtt = atts.getNamedItem("style");
		Node valueAtt = atts.getNamedItem("value");
		Node indentAtt = atts.getNamedItem("indent");
		int style = IBulletParagraph.CIRCLE;
		int indent = -1;
		String text = null;
		boolean addSpace = true;

		if (addSpaceAtt != null) {
			String value = addSpaceAtt.getNodeValue();
			addSpace = value.equalsIgnoreCase("true");
		}
		if (styleAtt != null) {
			String value = styleAtt.getNodeValue();
			if (value.equalsIgnoreCase("text")) {
				style = IBulletParagraph.TEXT;
			} else if (value.equalsIgnoreCase("image")) {
				style = IBulletParagraph.IMAGE;
			}
		}
		if (valueAtt != null) {
			text = valueAtt.getNodeValue();
		}
		if (indentAtt != null) {
			String value = indentAtt.getNodeValue();
			try {
				indent = Integer.parseInt(value);
			} catch (NumberFormatException e) {
			}
		}

		BulletParagraph p = new BulletParagraph(addSpace);
		p.setIndent(indent);
		p.setBulletStyle(style);
		p.setBulletText(text);

		processSegments(p, children, expandURLs);
		return p;
	}

	private void processSegments(
		Paragraph p,
		NodeList children,
		boolean expandURLs) {
		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			IParagraphSegment segment = null;

			if (child.getNodeType() == Node.TEXT_NODE) {
				String value = child.getNodeValue();

				if (value != null && !isIgnorableWhiteSpace(value, false)) {
					p.parseRegularText(
						value,
						expandURLs,
						getHyperlinkSettings(),
						null);
				}
			} else if (child.getNodeType() == Node.ELEMENT_NODE) {
				String name = child.getNodeName();
				if (name.equalsIgnoreCase("img")) {
					segment = processImageSegment(child);
				} else if (name.equalsIgnoreCase("a")) {
					segment =
						processHyperlinkSegment(child, getHyperlinkSettings());
				} else if (name.equalsIgnoreCase("text")) {
					processTextSegment(p, expandURLs, child);
				} else if (name.equalsIgnoreCase("b")) {
					String text = getNodeText(child).trim();
					String fontId = JFaceResources.BANNER_FONT;
					p.parseRegularText(
						text,
						expandURLs,
						getHyperlinkSettings(),
						fontId);
				}
			}
			if (segment != null) {
				p.addSegment(segment);
			}
		}
	}

	private boolean isIgnorableWhiteSpace(String text, boolean ignoreSpaces) {
		for (int i = 0; i < text.length(); i++) {
			char c = text.charAt(i);
			if (ignoreSpaces && c == ' ')
				continue;
			if (c == '\n' || c == '\r' || c == '\f')
				continue;
			return false;
		}
		return true;
	}

	private IParagraphSegment processImageSegment(Node image) {
		ImageSegment segment = new ImageSegment();
		NamedNodeMap atts = image.getAttributes();
		Node id = atts.getNamedItem("href");
		Node align = atts.getNamedItem("align");
		if (id != null) {
			String value = id.getNodeValue();
			segment.setObjectId(value);
		}
		if (align != null) {
			String value = align.getNodeValue().toLowerCase();
			if (value.equals("top"))
				segment.setVerticalAlignment(ImageSegment.TOP);
			else if (value.equals("middle"))
				segment.setVerticalAlignment(ImageSegment.MIDDLE);
			else if (value.equals("bottom"))
				segment.setVerticalAlignment(ImageSegment.BOTTOM);
		}
		return segment;
	}

	private String getNodeText(Node node) {
		NodeList children = node.getChildNodes();
		String text = "";
		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			if (child.getNodeType() == Node.TEXT_NODE) {
				text += child.getNodeValue();
			}
		}
		return text;
	}

	private IParagraphSegment processHyperlinkSegment(
		Node link,
		HyperlinkSettings settings) {
		String text = getNodeText(link);
		HyperlinkSegment segment = new HyperlinkSegment(text, settings, null);
		NamedNodeMap atts = link.getAttributes();
		Node href = atts.getNamedItem("href");
		if (href != null) {
			String value = href.getNodeValue();
			segment.setActionId(value);
		}
		Node arg = atts.getNamedItem("arg");
		if (arg != null) {
			String value = arg.getNodeValue();
			segment.setArg(value);
		}
		return segment;
	}

	private void processTextSegment(
		Paragraph p,
		boolean expandURLs,
		Node textNode) {
		String text = getNodeText(textNode).trim();

		NamedNodeMap atts = textNode.getAttributes();
		Node font = atts.getNamedItem("font");
		String fontId = null;
		if (font != null) {
			fontId = font.getNodeValue();
		}
		p.parseRegularText(text, expandURLs, getHyperlinkSettings(), fontId);
	}

	public void parseRegularText(String regularText, boolean convertURLs)
		throws CoreException {
		reset();
		
		if (regularText==null) return;

		Paragraph p = new Paragraph(true);
		paragraphs.add(p);
		int pstart = 0;

		for (int i = 0; i < regularText.length(); i++) {
			char c = regularText.charAt(i);
			if (p == null) {
				p = new Paragraph(true);
				paragraphs.add(p);
			}
			if (c == '\n') {
				String text = regularText.substring(pstart, i);
				pstart = i + 1;
				p.parseRegularText(
					text,
					convertURLs,
					getHyperlinkSettings(),
					null);
				p = null;
			}
		}
		if (p != null) {
			// no new line
			String text = regularText.substring(pstart);
			p.parseRegularText(text, convertURLs, getHyperlinkSettings(), null);
		}
	}

	public HyperlinkSettings getHyperlinkSettings() {
		if (hyperlinkSettings == null) {
			hyperlinkSettings = new LocalHyperlinkSettings();
		}
		return hyperlinkSettings;
	}

	public void setHyperlinkSettings(HyperlinkSettings settings) {
		this.hyperlinkSettings = settings;
	}

	public void setURLListener(IHyperlinkListener urlListener) {
		this.urlListener = urlListener;
	}

	private void reset() {
		if (paragraphs == null)
			paragraphs = new Vector();
		paragraphs.clear();
		selectedLinkIndex = -1;
		hyperlinks = null;
	}

	IHyperlinkSegment[] getHyperlinks() {
		if (hyperlinks != null || paragraphs == null)
			return hyperlinks;
		Vector result = new Vector();
		for (int i = 0; i < paragraphs.size(); i++) {
			IParagraph p = (IParagraph) paragraphs.get(i);
			IParagraphSegment[] segments = p.getSegments();
			for (int j = 0; j < segments.length; j++) {
				if (segments[j] instanceof IHyperlinkSegment)
					result.add(segments[j]);
			}
		}
		hyperlinks =
			(IHyperlinkSegment[]) result.toArray(
				new IHyperlinkSegment[result.size()]);
		return hyperlinks;
	}

	public IHyperlinkSegment findHyperlinkAt(int x, int y) {
		IHyperlinkSegment[] links = getHyperlinks();
		for (int i = 0; i < links.length; i++) {
			if (links[i].contains(x, y))
				return links[i];
		}
		return null;
	}
	public ITextSegment findSegmentAt(int x, int y) {
		for (int i = 0; i < paragraphs.size(); i++) {
			IParagraph p = (IParagraph) paragraphs.get(i);
			ITextSegment segment = p.findSegmentAt(x, y);
			if (segment != null)
				return segment;
		}
		return null;
	}

	public IHyperlinkSegment getSelectedLink() {
		if (selectedLinkIndex == -1)
			return null;
		return hyperlinks[selectedLinkIndex];
	}

	public boolean traverseLinks(boolean next) {
		IHyperlinkSegment[] links = getHyperlinks();
		if (links == null)
			return false;
		int size = links.length;
		if (next) {
			selectedLinkIndex++;
		} else
			selectedLinkIndex--;

		if (selectedLinkIndex < 0 || selectedLinkIndex > size - 1) {
			selectedLinkIndex = -1;
		}
		return selectedLinkIndex != -1;
	}

	public void selectLink(IHyperlinkSegment link) {
		if (link == null)
			selectedLinkIndex = -1;
		else {
			IHyperlinkSegment[] links = getHyperlinks();
			selectedLinkIndex = -1;
			if (links == null)
				return;
			for (int i = 0; i < links.length; i++) {
				if (links[i].equals(link)) {
					selectedLinkIndex = i;
					break;
				}
			}
		}
	}

	public boolean hasFocusSegments() {
		IHyperlinkSegment[] links = getHyperlinks();
		if (links.length > 0)
			return true;
		return false;
	}

	public void dispose() {
		if (hyperlinkSettings instanceof LocalHyperlinkSettings)
			hyperlinkSettings.dispose();
	}
}
