/*******************************************************************************
 * Copyright (c) 2007, 2010 Wind River Systems, 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:
 * Michael Scharf (Wind River) - initial API and implementation
 * Martin Oberhuber (Wind River) - [168197] Fix Terminal for CDC-1.1/Foundation-1.1
 * Anton Leherbauer (Wind River) - [219589] Copy an entire line selection
 *******************************************************************************/
package org.eclipse.tm.internal.terminal.textcanvas;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.swt.graphics.Point;
import org.eclipse.tm.terminal.model.ITerminalTextDataReadOnly;
import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;

abstract public class AbstractTextCanvasModel implements ITextCanvasModel {
	protected List fListeners = new ArrayList();
	private int fCursorLine;
	private int fCursorColumn;
	private boolean fShowCursor;
	private long fCursorTime;
	private boolean fCursorIsEnabled;
	private final ITerminalTextDataSnapshot fSnapshot;
	private int fLines;

	private int fSelectionStartLine=-1;
	private int fSeletionEndLine;
	private int fSelectionStartCoumn;
	private int fSelectionEndColumn;
	private ITerminalTextDataSnapshot fSelectionSnapshot;
	private String fCurrentSelection=""; //$NON-NLS-1$
	private final Point fSelectionAnchor=new Point(0,0);
	/**
	 * do not update while update is running
	 */
	boolean fInUpdate;
	private int fCols;

	public AbstractTextCanvasModel(ITerminalTextDataSnapshot snapshot) {
		fSnapshot=snapshot;
		fLines=fSnapshot.getHeight();
	}
	public void addCellCanvasModelListener(ITextCanvasModelListener listener) {
		fListeners.add(listener);
	}

	public void removeCellCanvasModelListener(ITextCanvasModelListener listener) {
		fListeners.remove(listener);
	}

	protected void fireCellRangeChanged(int x, int y, int width, int height) {
		for (Iterator iter = fListeners.iterator(); iter.hasNext();) {
			ITextCanvasModelListener listener = (ITextCanvasModelListener) iter.next();
			listener.rangeChanged(x, y, width, height);
		}
	}
	protected void fireDimensionsChanged( int width,int height) {
		for (Iterator iter = fListeners.iterator(); iter.hasNext();) {
			ITextCanvasModelListener listener = (ITextCanvasModelListener) iter.next();
			listener.dimensionsChanged(width,height);
		}

	}
	protected void fireTerminalDataChanged() {
		for (Iterator iter = fListeners.iterator(); iter.hasNext();) {
			ITextCanvasModelListener listener = (ITextCanvasModelListener) iter.next();
			listener.terminalDataChanged();
		}

	}

	public ITerminalTextDataReadOnly getTerminalText() {
		return fSnapshot;
	}
	protected ITerminalTextDataSnapshot getSnapshot() {
		return fSnapshot;
	}
	protected void updateSnapshot() {
		if(!fInUpdate && fSnapshot.isOutOfDate()) {
			fInUpdate=true;
			try {
				fSnapshot.updateSnapshot(false);
				if(fSnapshot.hasTerminalChanged())
					fireTerminalDataChanged();
				// TODO why does hasDimensionsChanged not work??????
				//			if(fSnapshot.hasDimensionsChanged())
				//				fireDimensionsChanged();
				if(fLines!=fSnapshot.getHeight() || fCols!=fSnapshot.getWidth()) {
					fireDimensionsChanged(fSnapshot.getWidth(),fSnapshot.getHeight());
					fLines=fSnapshot.getHeight();
					fCols=fSnapshot.getWidth();
				}
				int y=fSnapshot.getFirstChangedLine();
				// has any line changed?
				if(y<Integer.MAX_VALUE) {
					int height=fSnapshot.getLastChangedLine()-y+1;
					fireCellRangeChanged(0, y, fSnapshot.getWidth(), height);
				}

			} finally {
				fInUpdate=false;
			}
		}
	}
	/**
	 * must be called from the UI thread
	 */
	public void update() {
		// do the poll....
		updateSnapshot();
		updateSelection();
		updateCursor();
	}


	public int getCursorColumn() {
		return fCursorColumn;
	}

	public int getCursorLine() {
		return fCursorLine;
	}

	public boolean isCursorOn() {
		return fShowCursor && fCursorIsEnabled;
	}
	/**
	 * should be called regularly to draw an update of the
	 * blinking cursor
	 */
	protected void updateCursor() {
		if(!fCursorIsEnabled)
			return;
		int cursorLine=getSnapshot().getCursorLine();
		int cursorColumn=getSnapshot().getCursorColumn();
		// if cursor at the end put it to the end of the
		// last line...
		if(cursorLine>=getSnapshot().getHeight()) {
			cursorLine=getSnapshot().getHeight()-1;
			cursorColumn=getSnapshot().getWidth()-1;
		}
		// has the cursor moved?
		if(fCursorLine!=cursorLine || fCursorColumn!=cursorColumn) {
			// hide the old cursor!
			fShowCursor=false;
			// clean the previous cursor
			// bug 206363: paint also the char to the left and right of the cursor - see also below
			int col=fCursorColumn;
			int width=2;
			if(col>0) {
				col--;
				width++;
			}
			fireCellRangeChanged(col, fCursorLine, width, 1);
			// the cursor is shown when it moves!
			fShowCursor=true;
			fCursorTime=System.currentTimeMillis();
			fCursorLine=cursorLine;
			fCursorColumn=cursorColumn;
			// and draw the new cursor
			fireCellRangeChanged(fCursorColumn, fCursorLine, 1, 1);
		} else {
			long t=System.currentTimeMillis();
			// TODO make the cursor blink time customisable
			if(t-fCursorTime>500) {
				fShowCursor=!fShowCursor;
				fCursorTime=t;
				// on some windows machines, there is some left
				// over when updating the cursor .
				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=206363
				int col=fCursorColumn;
				int width=2;
				if(col>0) {
					col--;
					width++;
				}
				fireCellRangeChanged(col, fCursorLine, width, 1);
			}
		}
	}
	public void setVisibleRectangle(int startLine, int startCol, int height, int width) {
		fSnapshot.setInterestWindow(Math.max(0,startLine), Math.max(1,height));
		update();
	}
	protected void showCursor(boolean show) {
		fShowCursor=true;
	}
	public void setCursorEnabled(boolean visible) {
		fCursorTime=System.currentTimeMillis();
		fShowCursor=visible;
		fCursorIsEnabled=visible;
		fireCellRangeChanged(fCursorColumn, fCursorLine, 1, 1);
	}
	public boolean isCursorEnabled() {
		return fCursorIsEnabled;
	}

	public Point getSelectionEnd() {
		if(fSelectionStartLine<0)
			return null;
		else
			return new Point(fSelectionEndColumn, fSeletionEndLine);
	}

	public Point getSelectionStart() {
		if (fSelectionStartLine < 0)
			return null;
		else
			return new Point(fSelectionStartCoumn,fSelectionStartLine);
	}
	public Point getSelectionAnchor() {
		if(fSelectionStartLine<0)
			return null;
		return new Point(fSelectionAnchor.x,fSelectionAnchor.y);
	}
	public void setSelectionAnchor(Point anchor) {
		fSelectionAnchor.x=anchor.x;
		fSelectionAnchor.y=anchor.y;
	}

	public void setSelection(int startLine, int endLine, int startColumn, int endColumn) {
//		System.err.println(startLine+","+endLine+","+startColumn+","+endColumn);
		doSetSelection(startLine, endLine, startColumn, endColumn);
		fCurrentSelection=extractSelectedText();
	}
	private void doSetSelection(int startLine, int endLine, int startColumn, int endColumn) {
		assert(startLine<0 || startLine<=endLine);
		if(startLine>=0) {
			if(fSelectionSnapshot==null) {
				fSelectionSnapshot=fSnapshot.getTerminalTextData().makeSnapshot();
				fSelectionSnapshot.updateSnapshot(true);
			}
		} else if(fSelectionSnapshot!=null) {
			fSelectionSnapshot.detach();
			fSelectionSnapshot=null;
		}
		int oldStart=fSelectionStartLine;
		int oldEnd=fSeletionEndLine;
		fSelectionStartLine = startLine;
		fSeletionEndLine = endLine;
		fSelectionStartCoumn = startColumn;
		fSelectionEndColumn = endColumn;
		if(fSelectionSnapshot!=null) {
			fSelectionSnapshot.setInterestWindow(0, fSelectionSnapshot.getHeight());
		}
		int changedStart;
		int changedEnd;
		if(oldStart<0) {
			changedStart=fSelectionStartLine;
			changedEnd=fSeletionEndLine;
		} else if(fSelectionStartLine<0) {
			changedStart=oldStart;
			changedEnd=oldEnd;
		} else {
			changedStart=Math.min(oldStart, fSelectionStartLine);
			changedEnd=Math.max(oldEnd, fSeletionEndLine);
		}
		if(changedStart>=0) {
			fireCellRangeChanged(0, changedStart, fSnapshot.getWidth(), changedEnd-changedStart+1);
		}
	}

	public boolean hasLineSelection(int line) {
		if (fSelectionStartLine < 0)
			return false;
		else
			return line >= fSelectionStartLine && line <= fSeletionEndLine;
	}

	public String getSelectedText() {
		return fCurrentSelection;
	}
	/**
	 * Calculates the currently selected text
	 * @return the currently selected text
	 */
	private String extractSelectedText() {
		if(fSelectionStartLine<0 || fSelectionStartCoumn<0 || fSelectionSnapshot==null)
			return ""; //$NON-NLS-1$
		StringBuffer buffer=new StringBuffer();
		for (int line = fSelectionStartLine; line <= fSeletionEndLine; line++) {
			String text;
			char[] chars=fSelectionSnapshot.getChars(line);
			if(chars!=null) {
				text=new String(chars);
				if(line==fSeletionEndLine && fSelectionEndColumn >= 0)
					text=text.substring(0, Math.min(fSelectionEndColumn+1,text.length()));
				if(line==fSelectionStartLine)
					text=text.substring(Math.min(fSelectionStartCoumn,text.length()));
				// get rid of the empty space at the end of the lines
				// text=text.replaceAll("\000+$","");  //$NON-NLS-1$//$NON-NLS-2$
				// <J2ME-CDC-1.1 version>
				int i = text.length() - 1;
				while (i >= 0 && text.charAt(i) == '\000') {
					i--;
				}
				text = text.substring(0, i + 1);
				// </J2ME-CDC-1.1 version>
				// null means space
				text=text.replace('\000', ' ');
			} else {
				text=""; //$NON-NLS-1$
			}
			buffer.append(text);
			if(line < fSeletionEndLine)
				buffer.append('\n');
		}
		return buffer.toString();
	}
	private void updateSelection() {
		if (fSelectionSnapshot != null && fSelectionSnapshot.isOutOfDate()) {
			fSelectionSnapshot.updateSnapshot(true);
			// has the selection moved?
			if (fSelectionSnapshot != null && fSelectionStartLine >= 0 && fSelectionSnapshot.getScrollWindowSize() > 0) {
				int start = fSelectionStartLine + fSelectionSnapshot.getScrollWindowShift();
				int end = fSeletionEndLine + fSelectionSnapshot.getScrollWindowShift();
				if (start < 0)
					if (end >= 0)
						start = 0;
					else
						start = -1;
				doSetSelection(start, end, fSelectionStartCoumn, fSelectionEndColumn);
			}
			// check if the content of the selection has changed. If the content has
			// changed, clear the selection
			if (fCurrentSelection.length()>0 && fSelectionSnapshot != null
					&& fSelectionSnapshot.getFirstChangedLine() <= fSeletionEndLine
					&& fSelectionSnapshot.getLastChangedLine() >= fSelectionStartLine) {
				// has the selected text changed?
				if (!fCurrentSelection.equals(extractSelectedText())) {
					setSelection(-1, -1, -1, -1);
				}
			}
			// update the observed window...
			if (fSelectionSnapshot != null)
				// todo make -1 to work!
				fSelectionSnapshot.setInterestWindow(0, fSelectionSnapshot.getHeight());
		}
	}

}