/*******************************************************************************
 * 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.dnd.internal;

import org.eclipse.gef.SharedCursors;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jst.pagedesigner.dom.EditModelQuery;
import org.eclipse.jst.pagedesigner.dom.EditValidateUtil;
import org.eclipse.jst.pagedesigner.dom.IDOMPosition;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ST;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Caret;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.ui.StructuredTextEditor;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

/**
 * This class will 1. determine it's insertion or update 2. call validator
 * corresponding helper to resolve it.
 * 
 * @author mengbo
 */
public final class SourceViewerDragDropHelper {
	private static SourceViewerDragDropHelper _instance;

	/**
	 * @return the singleton instance
	 */
	public static SourceViewerDragDropHelper getInstance() {
		if (_instance == null) {
			_instance = new SourceViewerDragDropHelper();
		}
		return _instance;
	}

	private SourceViewerDragDropHelper()
	{
	    // singleton, no external instantiation
	}
	
	private Point toControl(TextViewer textViewer, Point point) {
		return (textViewer != null ? textViewer.getTextWidget()
				.toControl(point) : point);
	}

	private int getDropOffset(StructuredTextEditor ste, Point pt) {
		StyledText st = ste.getTextViewer().getTextWidget();
		int offset = st.getCaretOffset();
		try {
			offset = st.getOffsetAtLocation(pt);
		} catch (IllegalArgumentException e) {
			boolean found = false;
			Point p = new Point((pt.x > 0 ? pt.x : 0), pt.y);
			// search nearest character
			for (; p.x > -1; p.x--) {
				try {
					offset = st.getOffsetAtLocation(p);

					/*
					 * Now that a valid offset has been found, try to place at
					 * the end of the line
					 */
					if (ste.getTextViewer() != null
							&& ste.getTextViewer().getDocument() != null) {
						IRegion lineInfo = null;
						try {
							lineInfo = ste.getTextViewer().getDocument()
									.getLineInformationOfOffset(offset);
						} catch (BadLocationException e1) {
                            // ignore exception and fall-through with lineInfo == null
						}
						if (lineInfo != null)
							offset = lineInfo.getOffset()
									+ lineInfo.getLength();
					}

					found = true;
					break;
				} catch (IllegalArgumentException ex) {
					// for trying location, no need to catch.
				}
			}
			if (!found) {
				offset = st.getCharCount();
			}
		}
		return offset;
	}

	/**
	 * @param textEditor
	 * @param location
	 * @param caret
	 */
	public void updateCaret(StructuredTextEditor textEditor, Point location,
			Point caret) {
		TextViewer textViewer = textEditor.getTextViewer();
		if (textViewer != null) {
			Point pt = toControl(textViewer, location);
			StyledText st = textViewer.getTextWidget();

			// auto scroll
			Rectangle ca = st.getClientArea();
			int margin = st.getLineHeight();

			if (pt.y < margin) { // up
				st.invokeAction(ST.LINE_UP);
			} else if (pt.y > ca.height - margin) { // down
				st.invokeAction(ST.LINE_DOWN);
			}

			// draw insertion point
			int offset = getDropOffset(textEditor, pt);
			if (offset != st.getCaretOffset()) {
				st.setCaretOffset(offset);
				st.setSelection(offset);
			}

			Point newCaret = st.getLocationAtOffset(offset);
			if (newCaret.equals(caret)) {
				return;
			}

			Caret ct = st.getCaret();
			Point size = ct.getSize();

			GC gc = new GC(st);
			gc.setXORMode(true);
			gc.setLineWidth(size.x);

			// erase old caret
			if (caret != null) {
				Color originalForeground = gc.getForeground();
				gc.setForeground(st.getBackground());
				gc.drawLine(caret.x, caret.y, caret.x, caret.y + size.y);
				gc.setForeground(originalForeground);
			}

			st.redraw();
			st.update();

			// draw new caret
			if (caret == null) {
				caret = newCaret;
			} else {
				caret.x = newCaret.x;
				caret.y = newCaret.y;
			}
			if (ct.getImage() != null) {
				gc.drawImage(ct.getImage(), caret.x, caret.y);
			} else {
				gc.drawLine(caret.x, caret.y, caret.x, caret.y + size.y);
			}

			gc.dispose();
		}
	}

	/**
	 * @param textEditor
	 * @param location
	 */
	public void updateCaret(StructuredTextEditor textEditor, Point location) {
		TextViewer textViewer = textEditor.getTextViewer();
		if (textViewer != null) {
			Point pt = toControl(textViewer, location);
			StyledText st = textViewer.getTextWidget();

			// auto scroll
			Rectangle ca = st.getClientArea();
			int margin = st.getLineHeight();

			if (pt.y < margin) { // up
				st.invokeAction(ST.LINE_UP);
			} else if (pt.y > ca.height - margin) { // down
				st.invokeAction(ST.LINE_DOWN);
			}

			// draw insertion point
			int offset = getDropOffset(textEditor, pt);
			if (offset != st.getCaretOffset()) {
				st.setCaretOffset(offset);
				st.setSelection(offset);
			}
		}
	}

	/**
	 * @param textEditor
	 * @param location
	 * @return the caret offset
	 */
	public int showCaret(StructuredTextEditor textEditor, int location) {
		StyledText text = textEditor.getTextViewer().getTextWidget();
		text.setCursor(SharedCursors.CURSOR_TREE_ADD);
		text.setCaretOffset(location);
		if (!text.isFocusControl()) {
			text.setFocus();
		}
		return text.getCaretOffset();
	}

	/**
	 * @param node
	 * @return the model query for the node or null if not available
	 */
	protected ModelQuery getModelQuery(Node node) {
		if (node.getNodeType() == Node.DOCUMENT_NODE) {
			return ModelQueryUtil.getModelQuery((Document) node);
		}
        return ModelQueryUtil.getModelQuery(node.getOwnerDocument());
	}

	/**
	 * @param caretPos
	 * @param element
	 * @return the position 
	 */
	public IDOMPosition findPosition(int caretPos, Node element) {
		EditValidateUtil.validNode(element);
		IDOMPosition position = EditModelQuery.getInstance().createDomposition(
				((IDOMNode) element).getModel(), caretPos, false);
		return position;
	}

	/**
	 * @param viewer
	 * @param node
	 */
	public void format(TextViewer viewer, Node node) {
		if (node == null) {
			return;
		}
		Node tmp;
		int start, offset;
		if (node.getPreviousSibling() != null) {
			tmp = node.getPreviousSibling();
			start = ((IndexedRegion) tmp).getEndOffset();
		} else {
			tmp = node;
			start = ((IndexedRegion) tmp).getStartOffset();
		}
		if (node.getNextSibling() != null) {
			tmp = node.getNextSibling();
			offset = ((IndexedRegion) tmp).getStartOffset() - start;
		} else {
			tmp = node;
			offset = ((IndexedRegion) tmp).getEndOffset() - start;
		}
		viewer.setSelectedRange(start, offset);
		viewer.doOperation(ISourceViewer.FORMAT);
	}

	/**
	 * @param textEditor
	 * @param reset
	 */
	public void changeCaret(StructuredTextEditor textEditor, boolean reset) {
		if (reset) {
			StyledText text = textEditor.getTextViewer().getTextWidget();
			text.setCursor(new Cursor(null, SWT.CURSOR_IBEAM));
		}
	}

	/**
	 * @param textEditor
	 * @param locationOffset
	 * @return the location offset
	 */
	public int getValidLocation(StructuredTextEditor textEditor,
			int locationOffset) {
		Node node = getCaretNode(textEditor, locationOffset);
		if (node == null) {
			// empty page?
			return 0;
		}
		if (node.getNodeType() == Node.TEXT_NODE) {
			return locationOffset;
		}
		return calculateCaretLocation(node, locationOffset);
	}

	/**
	 * @param textEditor
	 * @param location
	 * @return the offset
	 */
	public int getOffset(StructuredTextEditor textEditor, Point location) {
		StyledText text = textEditor.getTextViewer().getTextWidget();
		return text.getOffsetAtLocation(location);
	}

	// private IStructuredModel getModel(StructuredTextEditor textEditor)
	// {
	// IStructuredModel model = null;
	// if (textEditor.getDocumentProvider() != null)
	// {
	// if (textEditor.getDocumentProvider() instanceof IModelProvider)
	// {
	// model = ((IModelProvider)
	// textEditor.getDocumentProvider()).getModel(textEditor.getEditorInput());
	// }
	// else
	// {
	// IDocument doc =
	// textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
	// if (doc instanceof IDocument)
	// {
	// model =
	// StructuredModelManager.getModelManager().getExistingModelForEdit(doc);
	// if (model == null)
	// {
	// model =
	// StructuredModelManager.getModelManager().getExistingModelForEdit((IDocument)
	// doc);
	// }
	// }
	// }
	// }
	// return model;
	// }

	/**
	 * @param textEditor
	 * @param pos
	 * @return the node
	 */
	public Node getCaretNode(StructuredTextEditor textEditor, int pos) {
        // TODO: getModel is deprecated
		IStructuredModel model = textEditor.getModel();
		// getModel(textEditor);
		if (model == null) {
			return null;
		}
		IndexedRegion inode = model.getIndexedRegion(pos);
		if (inode == null) {
			inode = model.getIndexedRegion(pos - 1);
		}
		return (inode instanceof Node) ? (Node) inode : null;
	}

	/**
	 * Calculate and adjust the location in compare with Node.
	 * 
	 * @param node
	 * @param location
	 * @return the location
	 */
	public int calculateCaretLocation(Node node, int location) {
		int pos[][] = new int[2][2];
		pos[0][0] = EditModelQuery.getNodeStartIndex(node);
		pos[0][1] = EditModelQuery.getNodeStartNameEndIndex(node);
		pos[1][0] = EditModelQuery.getNodeEndNameStartIndex(node);
		pos[1][1] = EditModelQuery.getNodeEndIndex(node);
		if (pos[0][0] >= location || pos[1][0] == location
				|| pos[1][1] <= location) {
			return location;
		} else if (pos[0][0] <= location && pos[0][1] >= location) {
			if (((pos[0][1] + pos[0][0]) / 2) >= location) {
				return pos[0][0];
			}
            return pos[0][1];
		} else if (pos[1][0] <= location && pos[1][1] >= location) {
			if (((pos[1][1] + pos[1][0]) / 2) >= location) {
				return pos[1][0];
			}
            return pos[1][1];
		}
		return location;
	}
}
