/*******************************************************************************
 * Copyright (c) 2000, 2008 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.jface.text.tests;

import junit.framework.TestCase;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension4;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.IUndoManager;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry;
import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;

/**
 * Tests for DefaultUndoManager. Changed from the JFace original to creates
 * and test against a structured document.
 */
public abstract class AbstractUndoManagerTest extends TestCase {

	/** The maximum undo level. */
	private static final int MAX_UNDO_LEVEL= 256;

	/** The shell. */
	private Shell fShell;
	/** The text viewer. */
	private ITextViewer fTextViewer;
	/** The undo manager. */
	private IUndoManager fUndoManager;

	private static final int LOOP_COUNT= 20;

	//--- Static data sets for comparing scenarios - obtained from capturing random data ---
	/** Original document */
	private static final String INITIAL_DOCUMENT_CONTENT= "+7cyg:/F!T4KnW;0+au$t1G%(`Z|u'7'_!-k?<c\"2Y.]CwsO.r";
	/** Replacement string */
	private static final String [] REPLACEMENTS= { ">", "F", "M/r-*", "-", "bl", "", "}%/#", "", "k&", "f", "\\g", "c!x", "TLG-", "NPO", "Rp9u", "", "X", "W(", ")z", "oe", "", "h*", "t", "I", "X=N>", "2yt", "&Z", "2)W=", ":K", "P9S", "s8t8o", "", "", "5{7", "%", "", "v3", "Wz", "sH", "3c", "8", "ol", ",6$", "94[#", ".~", "n", ">", "9", "W", ",(FW", "Q", "^", "Bq", "$", "re", "", "9", "8[", "Mx", "4b", "$6", "F", "8s]", "o", "-", "E&6", "S\\", "/", "z.a", "4ai", "b", ")", "", "l", "VU", "7M+Ql", "xZ?x", "xx", "lc", "b", "A", "!", "4pSU", "", "{J", "H", "l>_", "n&9", "", "&`", ";igQxq", "", ">", ";\"", "k\\`]G", "o{?", "", "K", "_6", "="};
	/** Position/offset pairs */
	private static final int [] POSITIONS= { 18, 2, 43, 1, 3, 2, 28, 3, 35, 1, 23, 5, 32, 2, 30, 1, 22, 1, 37, 0, 23, 3, 43, 2, 46, 1, 17, 1, 36, 6, 17, 5, 30, 4, 25, 1, 2, 2, 30, 0, 37, 3, 28, 1, 30, 2, 20, 5, 33, 1, 29, 1, 15, 2, 21, 2, 24, 4, 38, 3, 8, 0, 33, 2, 15, 2, 25, 0, 8, 2, 20, 3, 43, 2, 44, 1, 44, 2, 32, 2, 40, 2, 32, 3, 12, 2, 38, 3, 33, 2, 46, 0, 13, 3, 45, 0, 16, 2, 3, 2, 44, 0, 48, 0, 18, 5, 7, 6, 7, 3, 40, 0, 9, 1, 16, 3, 28, 3, 36, 1, 35, 2, 0, 3, 6, 1, 10, 4, 14, 2, 15, 3, 33, 1, 36, 0, 37, 0, 4, 3, 31, 3, 33, 3, 11, 3, 20, 2, 25, 3, 4, 3, 7, 3, 17, 0, 3, 1, 31, 3, 34, 1, 21, 0, 33, 1, 17, 4, 9, 1, 26, 3, 2, 3, 12, 1, 26, 3, 9, 5, 5, 0, 31, 3, 0, 3, 12, 1, 1, 1, 3, 0, 39, 0, 9, 2, 2, 0, 28, 2};

	private static final boolean DEBUG= false;


	/*
	 * @see TestCase#TestCase(String)
	 */
	public AbstractUndoManagerTest(final String name) {
		super(name);
	}

	/*
	 *  @see TestCase#setUp()
	 */
	protected void setUp() {
		fShell= new Shell();
		fUndoManager= createUndoManager(MAX_UNDO_LEVEL);
		fTextViewer= new TextViewer(fShell, SWT.NONE);
		fTextViewer.setUndoManager(fUndoManager);
		fUndoManager.connect(fTextViewer);
	}

	abstract protected IUndoManager createUndoManager(int maxUndoLevel);

	/*
	 *  @see TestCase#tearDown()
	 */
	protected void tearDown() {
		fUndoManager.disconnect();
		fUndoManager= null;
		fShell.dispose();
		fShell= null;
		fTextViewer= null;
	}

	/**
	 * Test for line delimiter conversion.
	 */
	public void testConvertLineDelimiters() {
		final String original= "a\r\nb\r\n";
		final IDocument document= createDocument(original);
		fTextViewer.setDocument(document);

		try {
			document.replace(1, 2, "\n");
			document.replace(3, 2, "\n");
		} catch (BadLocationException e) {
			assertTrue(false);
		}

		assertTrue(fUndoManager.undoable());
		fUndoManager.undo();
		assertTrue(fUndoManager.undoable());
		fUndoManager.undo();

		final String reverted= document.get();

		assertEquals(original, reverted);
	}

	/**
	 * Randomly applies document changes.
	 */
	public void testRandomAccess() {
		final int RANDOM_STRING_LENGTH= 50;
		final int RANDOM_REPLACE_COUNT= 100;

		assertTrue(RANDOM_REPLACE_COUNT >= 1);
		assertTrue(RANDOM_REPLACE_COUNT <= MAX_UNDO_LEVEL);

		String original= createRandomString(RANDOM_STRING_LENGTH);
		final IDocument document= createDocument(original);
		fTextViewer.setDocument(document);

		doChange(document, RANDOM_REPLACE_COUNT);

		assertTrue(fUndoManager.undoable());
		while (fUndoManager.undoable())
			fUndoManager.undo();

		final String reverted= document.get();
		assertEquals(original, reverted);
	}

	private void doChange(IDocument document, int count) {
		try {
			String before= document.get();

			if (DEBUG)
				System.out.println(before);

			Position [] positions= new Position[count];
			String [] strings= new String[count];
			for (int i= 0; i < count; i++) {
				final Position position= createRandomPositionPoisson(document.getLength());
				final String string= createRandomStringPoisson();
				document.replace(position.getOffset(), position.getLength(), string);
				positions[i]= position;
				strings[i]= string;
			}

			if (DEBUG) {
				System.out.print("{ ");
				for (int i=0; i<count; i++) {
					System.out.print(positions[i].getOffset());
					System.out.print(", ");
					System.out.print(positions[i].getLength());
					System.out.print(", ");
				}
				System.out.println(" }");
				System.out.print("{ ");
				for (int i=0; i<count; i++) {
					System.out.print("\"");
					System.out.print(strings[i]);
					System.out.print("\", ");
				}
				System.out.println(" }");
			}
		} catch (BadLocationException e) {
			assertTrue(false);
		}
	}

	// repeatable test case for comparing success/failure among different tests
	private void doRepeatableChange(IDocument document) {
		assertTrue(POSITIONS.length >= (2 * REPLACEMENTS.length));
		try {
			for (int i= 0; i < REPLACEMENTS.length; i++) {
				int offset= POSITIONS[i*2];
				int length= POSITIONS[i*2+1];
				if (document.getLength() > offset + length)
					document.replace(offset, length, REPLACEMENTS[i]);
				else
					document.replace(0,0, REPLACEMENTS[i]);
			}
		} catch (BadLocationException e) {
			assertTrue(false);
		}
	}

	public void testLoopRandomAccessAsCompound() {
		int i= 0;
		while (i < LOOP_COUNT) {
			fUndoManager.reset();
			testRandomAccessAsCompound();
			i++;
		}
	}

	public void testLoopRandomAccess() {
		int i= 0;
		while (i < LOOP_COUNT) {
			fUndoManager.reset();
			testRandomAccess();
			i++;
		}
	}

	public void testLoopRandomAccessAsUnclosedCompound() {
		int i= 0;
		while (i < LOOP_COUNT) {
			fUndoManager.reset();
			testRandomAccessAsUnclosedCompound();
			i++;
		}
	}

	public void testLoopConvertLineDelimiters() {
		int i= 0;
		while (i < LOOP_COUNT) {
			fUndoManager.reset();
			testConvertLineDelimiters();
			i++;
		}
	}

	public void testLoopRandomAccessWithMixedCompound() {
		int i= 0;
		while (i < LOOP_COUNT) {
			fUndoManager.reset();
			testRandomAccessWithMixedCompound();
			i++;
		}
	}

	public void testRandomAccessAsCompound() {
		final int RANDOM_STRING_LENGTH= 50;
		final int RANDOM_REPLACE_COUNT= 100;

		assertTrue(RANDOM_REPLACE_COUNT >= 1);
		assertTrue(RANDOM_REPLACE_COUNT <= MAX_UNDO_LEVEL);

		String original= createRandomString(RANDOM_STRING_LENGTH);
		final IDocument document= createDocument(original);
		fTextViewer.setDocument(document);

		fUndoManager.beginCompoundChange();
		doChange(document, RANDOM_REPLACE_COUNT);
		fUndoManager.endCompoundChange();

		assertTrue(fUndoManager.undoable());
		while (fUndoManager.undoable())
			fUndoManager.undo();
		assertTrue(!fUndoManager.undoable());

		final String reverted= document.get();

		assertEquals(original, reverted);
	}

	/**
	 * Test case for https://bugs.eclipse.org/bugs/show_bug.cgi?id=88172
	 */
	public void testRandomAccessAsUnclosedCompound() {

		final int RANDOM_STRING_LENGTH= 50;
		final int RANDOM_REPLACE_COUNT= 100;

		assertTrue(RANDOM_REPLACE_COUNT >= 1);
		assertTrue(RANDOM_REPLACE_COUNT <= MAX_UNDO_LEVEL);

		String original= createRandomString(RANDOM_STRING_LENGTH);
		final IDocument document= createDocument(original);
		fTextViewer.setDocument(document);

		fUndoManager.beginCompoundChange();
		doChange(document, RANDOM_REPLACE_COUNT);
		// do not close the compound.
		// fUndoManager.endCompoundChange();

		assertTrue(fUndoManager.undoable());
		while (fUndoManager.undoable())
			fUndoManager.undo();
		assertTrue(!fUndoManager.undoable());

		final String reverted= document.get();

		assertEquals(original, reverted);
	}

	public void testRandomAccessWithMixedCompound() {

		final int RANDOM_STRING_LENGTH= 50;
		final int RANDOM_REPLACE_COUNT= 10;
		final int NUMBER_COMPOUNDS= 5;
		final int NUMBER_ATOMIC_PER_COMPOUND= 3;

		assertTrue(RANDOM_REPLACE_COUNT >= 1);
		assertTrue(NUMBER_COMPOUNDS * (1 + NUMBER_ATOMIC_PER_COMPOUND) * RANDOM_REPLACE_COUNT <= MAX_UNDO_LEVEL);

		String original= createRandomString(RANDOM_STRING_LENGTH);
		final IDocument document= createDocument(original);
		fTextViewer.setDocument(document);

		for (int i= 0; i < NUMBER_COMPOUNDS; i++) {
			fUndoManager.beginCompoundChange();
			doChange(document, RANDOM_REPLACE_COUNT);
			fUndoManager.endCompoundChange();
			assertTrue(fUndoManager.undoable());
			for (int j= 0; j < NUMBER_ATOMIC_PER_COMPOUND; j++) {
				doChange(document, RANDOM_REPLACE_COUNT);
				assertTrue(fUndoManager.undoable());
			}
		}

		assertTrue(fUndoManager.undoable());
		while (fUndoManager.undoable())
			fUndoManager.undo();
		assertTrue(!fUndoManager.undoable());

		final String reverted= document.get();

		assertEquals(original, reverted);
	}

	public void testRepeatableAccess() {
		assertTrue(REPLACEMENTS.length <= MAX_UNDO_LEVEL);

		final IDocument document= createDocument(INITIAL_DOCUMENT_CONTENT);
		fTextViewer.setDocument(document);

		doRepeatableChange(document);

		assertTrue(fUndoManager.undoable());
		while (fUndoManager.undoable())
			fUndoManager.undo();

		final String reverted= document.get();

		assertEquals(INITIAL_DOCUMENT_CONTENT, reverted);
	}

	public void testRepeatableAccessAsCompound() {
		assertTrue(REPLACEMENTS.length <= MAX_UNDO_LEVEL);

		final IDocument document= createDocument(INITIAL_DOCUMENT_CONTENT);
		fTextViewer.setDocument(document);

		fUndoManager.beginCompoundChange();
		doRepeatableChange(document);
		fUndoManager.endCompoundChange();

		assertTrue(fUndoManager.undoable());
		fUndoManager.undo();
		// with a single compound, there should be only one undo
		assertFalse(fUndoManager.undoable());

		final String reverted= document.get();

		assertEquals(INITIAL_DOCUMENT_CONTENT, reverted);
	}

	public void testRepeatableAccessAsUnclosedCompound() {
		assertTrue(REPLACEMENTS.length <= MAX_UNDO_LEVEL);

		final IDocument document= createDocument(INITIAL_DOCUMENT_CONTENT);
		fTextViewer.setDocument(document);

		fUndoManager.beginCompoundChange();
		doRepeatableChange(document);

		assertTrue(fUndoManager.undoable());
		while (fUndoManager.undoable())
			fUndoManager.undo();

		final String reverted= document.get();

		assertEquals(INITIAL_DOCUMENT_CONTENT, reverted);
	}

	public void testRepeatableAccessWithMixedAndEmptyCompound() {
		assertTrue(REPLACEMENTS.length + 2 <= MAX_UNDO_LEVEL);

		final IDocument document= createDocument(INITIAL_DOCUMENT_CONTENT);
		fTextViewer.setDocument(document);

		fUndoManager.beginCompoundChange();
		doRepeatableChange(document);
		fUndoManager.endCompoundChange();
		assertTrue(fUndoManager.undoable());

		// insert an empty compound
		fUndoManager.beginCompoundChange();
		fUndoManager.endCompoundChange();

	    // insert the atomic changes
		doRepeatableChange(document);

		assertTrue(fUndoManager.undoable());
		while (fUndoManager.undoable())
			fUndoManager.undo();
		assertTrue(!fUndoManager.undoable());

		final String reverted= document.get();

		assertEquals(INITIAL_DOCUMENT_CONTENT, reverted);
	}

	public void testDocumentStamp() {
		final IDocument document= createDocument(INITIAL_DOCUMENT_CONTENT);
		fTextViewer.setDocument(document);
		long stamp= ((IDocumentExtension4)document).getModificationStamp();
		doChange(document, 1);
		fUndoManager.undo();
		assertEquals(stamp, ((IDocumentExtension4)document).getModificationStamp());

	}

	// see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=109104
	public void testDocumentStamp2() throws BadLocationException {
		final IDocument document= createDocument("");
		final int stringLength= 13;
		fTextViewer.setDocument(document);
		document.replace(0, 0, createRandomString(stringLength));
		long stamp= ((IDocumentExtension4)document).getModificationStamp();
		fUndoManager.undo();
		document.replace(0, 0, createRandomString(stringLength));
		assertFalse(stamp == ((IDocumentExtension4)document).getModificationStamp());

	}

	private static String createRandomString(int length) {
		final StringBuffer buffer= new StringBuffer();

		for (int i= 0; i < length; i++)
			buffer.append(getRandomCharacter());

		return buffer.toString();
	}

	private static final char getRandomCharacter() {
		// XXX should include \t
		return (char) (32 + 95 * Math.random());
	}

	private static String createRandomStringPoisson() {
		final int length= getRandomPoissonValue(2);
		return createRandomString(length);
	}
	
	private IDocument createDocument(String contents) {
		IModelHandler handler = ModelHandlerRegistry.getInstance().getHandlerForContentTypeId("org.eclipse.core.runtime.xml");
		BasicStructuredDocument document = (BasicStructuredDocument) handler.getDocumentLoader().createNewStructuredDocument();
		document.set(contents);
//		return new Document(contents);
		return document;
	}
	
	private static Position createRandomPositionPoisson(int documentLength) {

		float random= (float) Math.random();
		int offset= (int) (random * (documentLength + 1));

		// Catch potential rounding issue
		if (offset == documentLength + 1)
			offset= documentLength;

		int length= getRandomPoissonValue(2);
		if (offset + length > documentLength)
			length= documentLength - offset;

		return new Position(offset, length);
	}

	private static int getRandomPoissonValue(int mean) {
		final int MAX_VALUE= 10;

		final float random= (float) Math.random();
		float probability= 0;
		int i= 0;
		while (probability < 1 && i < MAX_VALUE) {
			probability += getPoissonDistribution(mean, i);
			if (random <= probability)
				break;
			i++;
		}
		return i;
	}

	private static float getPoissonDistribution(float lambda, int k) {
		return (float) (Math.exp(-lambda) * Math.pow(lambda, k) / faculty(k));
	}

	/**
	 * Returns the faculty of k.
	 *
	 * @param k the <code>int</code> for which to get the faculty
	 * @return the faculty
	 */
	private static final int faculty(int k) {
		return k == 0
			? 1
			: k * faculty(k - 1);
	}

}
