/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.text.tests.link;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.link.ILinkedModeListener;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.LinkedPositionGroup;


public class LinkedModeModelTest {

	private List<LinkedPosition> fPositions= new LinkedList<>();

	private List<IDocument[]> fDocumentMap= new ArrayList<>();

	@Test
	public void testUpdate() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");
		LinkedModeModel env= new LinkedModeModel();
		env.addGroup(group1);
		env.forceInstall();

		// edit the document
		doc1.replace(1, 9, "GRETCHEN");

		assertEquals(group1, "GRETCHEN");
		assertUnchanged(group1);
	}

	@Test
	public void testUpdateUnequalContent() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "Allumfasser");
		createLinkedPositions(group1, doc1, "Gott");
		LinkedModeModel env= new LinkedModeModel();
		env.addGroup(group1);
		env.forceInstall();

		// edit the document
		doc1.replace(GARTEN1.indexOf("Gott"), 4, "SUPERMAN");

		assertEquals(group1, "SUPERMAN");
		assertUnchanged(group1);
	}

	@Test
	public void testUpdateTwoGroups() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");

		LinkedPositionGroup group2= new LinkedPositionGroup();
		createLinkedPositions(group2, doc1, "FAUST");

		LinkedModeModel env= new LinkedModeModel();
		env.addGroup(group1);
		env.addGroup(group2);

		env.forceInstall();


		// edit the document
		doc1.replace(7, 3, "INE");

		assertEquals(group1, "MARGARINE");
		assertEquals(group2, "FAUST");
		assertUnchanged(group1, group2);
	}

	@Test
	public void testUpdateMultipleGroups() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");

		LinkedPositionGroup group2= new LinkedPositionGroup();
		createLinkedPositions(group2, doc1, "FAUST");

		LinkedModeModel env= new LinkedModeModel();
		env.addGroup(group1);
		env.addGroup(group2);

		env.forceInstall();


		// edit the document
		doc1.replace(7, 3, "INE");
		doc1.replace(42, 1, "");
		doc1.replace(44, 2, "GE");

		assertEquals(group1, "MARGARINE");
		assertEquals(group2, "AUGE");
		assertUnchanged(group1, group2);
	}

	@Test
	public void testUpdateMultiDocument() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);
		IDocument doc2= new Document(GARTEN2);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");
		createLinkedPositions(group1, doc2, "MARGARETE");

		LinkedPositionGroup group2= new LinkedPositionGroup();
		createLinkedPositions(group2, doc1, "FAUST");
		createLinkedPositions(group2, doc2, "FAUST");

		LinkedModeModel env= new LinkedModeModel();
		env.addGroup(group1);
		env.addGroup(group2);

		env.forceInstall();


		// edit the document
		doc1.replace(7, 3, "INE");
		doc1.replace(42, 1, "");
		doc1.replace(44, 2, "GE");

		assertEquals(group1, "MARGARINE");
		assertEquals(group2, "AUGE");
		assertUnchanged(group1, group2);

	}

	@Test
	public void testAddCompatibleGroups() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");

		LinkedPositionGroup group2= new LinkedPositionGroup();
		createLinkedPositions(group2, doc1, "FAUST");

		LinkedModeModel env= new LinkedModeModel();
		try {
			env.addGroup(group1);
			env.addGroup(group2);
		} catch (BadLocationException e) {
			assertFalse(true);
		}
		assertUnchanged(group1, group2);

	}

	@Test
	public void testAddIncompatibleGroups() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");

		LinkedPositionGroup group2= new LinkedPositionGroup();
		createLinkedPositions(group2, doc1, "MARGA");

		LinkedModeModel env= new LinkedModeModel();
		try {
			env.addGroup(group1);
			env.addGroup(group2);
		} catch (BadLocationException e) {
			return;
		}
		assertFalse(true);
	}

	@Test
	public void testAddNullGroup() throws BadLocationException {
		LinkedModeModel env= new LinkedModeModel();
		try {
			env.addGroup(null);
		} catch (IllegalArgumentException e) {
			return;
		}

		assertFalse(true);
	}

	@Test
	public void testAddGroupWhenSealed() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");
		LinkedModeModel env= new LinkedModeModel();
		env.addGroup(group1);
		env.forceInstall();

		LinkedPositionGroup group2= new LinkedPositionGroup();
		createLinkedPositions(group2, doc1, "FAUST");
		try {
			env.addGroup(group2);
		} catch (IllegalStateException e) {
			return;
		}

		assertFalse(true);
	}

	@Test
	public void testDoubleInstall() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");
		LinkedModeModel env= new LinkedModeModel();
		env.addGroup(group1);

		env.forceInstall();

		try {
			env.forceInstall();
		} catch (IllegalStateException e) {
			return;
		}

		assertFalse(true);
	}

	@Test
	public void testEmptyInstall() throws BadLocationException {
		LinkedModeModel env= new LinkedModeModel();

		try {
			env.forceInstall();
		} catch (IllegalStateException e) {
			return;
		}

		assertFalse(true);
	}

	@Test
	public void testNestedUpdate() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");

		LinkedPositionGroup group2= new LinkedPositionGroup();
		createLinkedPositions(group2, doc1, "FAUST");

		LinkedModeModel env= new LinkedModeModel();
		env.addGroup(group1);
		env.addGroup(group2);

		env.forceInstall();

		// second level

		LinkedPositionGroup group1_2= new LinkedPositionGroup();
		group1_2.addPosition(new LinkedPosition(doc1, 7, 3, LinkedPositionGroup.NO_STOP));


		LinkedModeModel childEnv= new LinkedModeModel();
		childEnv.addGroup(group1_2);
		childEnv.forceInstall();

		assertTrue(childEnv.isNested());
		assertFalse(env.isNested());


		// edit the document
		doc1.replace(7, 3, "INE");

		assertEquals(group1_2, "INE");
		assertEquals(group1, "MARGARINE");
		assertEquals(group2, "FAUST");
		assertUnchanged(group1, group2);
	}

	@Test
	public void testNestedForceInstall() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");

		LinkedPositionGroup group2= new LinkedPositionGroup();
		createLinkedPositions(group2, doc1, "FAUST");

		LinkedModeModel env= new LinkedModeModel();
		env.addGroup(group1);
		env.addGroup(group2);

		final boolean[] isExit= { false } ;
		env.addLinkingListener(new LinkedAdapter() {
			@Override
			public void left(LinkedModeModel environment, int flags) {
				isExit[0]= true;
			}
		});

		env.forceInstall();


		// second level

		LinkedPositionGroup group1_2= new LinkedPositionGroup();

		group1_2.addPosition(new LinkedPosition(doc1, 12, 3, LinkedPositionGroup.NO_STOP));

		LinkedModeModel childEnv= new LinkedModeModel();
		childEnv.addGroup(group1_2);
		childEnv.forceInstall();

		assertFalse(childEnv.isNested());
		assertTrue(isExit[0]);


		// edit the document
		doc1.replace(12, 3, "INE");

		assertEquals(group1_2, "INE");
	}

	@Test
	public void testNestedTryInstall() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");

		LinkedPositionGroup group2= new LinkedPositionGroup();
		createLinkedPositions(group2, doc1, "FAUST");

		LinkedModeModel env= new LinkedModeModel();
		env.addGroup(group1);
		env.addGroup(group2);
		env.forceInstall();


		// second level

		LinkedPositionGroup group1_2= new LinkedPositionGroup();
		group1_2.addPosition(new LinkedPosition(doc1, 12, 3, LinkedPositionGroup.NO_STOP));

		LinkedModeModel childEnv= new LinkedModeModel();
		childEnv.addGroup(group1_2);

		final boolean[] isExit= { false } ;
		env.addLinkingListener(new LinkedAdapter() {
			@Override
			public void left(LinkedModeModel environment, int flags) {
				isExit[0]= true;
			}
		});

		assertFalse(childEnv.tryInstall());
		assertFalse(childEnv.isNested());


		// edit the document
		doc1.replace(7, 3, "INE");

		assertEquals(group1, "MARGARINE");
		assertUnchanged(group1, group2);
	}

	@Test
	public void testOutsideUpdate() throws BadLocationException {
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");
		LinkedModeModel env= new LinkedModeModel();
		final boolean[] isExit= { false } ;
		env.addLinkingListener(new LinkedAdapter() {
			@Override
			public void left(LinkedModeModel environment, int flags) {
				isExit[0]= true;
			}
		});
		env.addGroup(group1);
		env.forceInstall();

		// edit the document
		doc1.replace(16, 2, "b");

		assertEquals(group1, "MARGARETE");
		assertFalse(isExit[0]);
		Assert.assertEquals("	MARGARETE:\n" +
				"	Verbrich mir, Heinrich!", doc1.get(0, 36));
//		assertUnchanged(group1); // would fail, since it was changed outside
	}

	@Test
	public void testOverlappingUpdate() throws BadLocationException {
		// a change partially touches a linked position, but also "in-between" text
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");
		LinkedModeModel env= new LinkedModeModel();
		final boolean[] isExit= { false } ;
		env.addLinkingListener(new LinkedAdapter() {
			@Override
			public void left(LinkedModeModel environment, int flags) {
				isExit[0]= true;
			}
		});
		env.addGroup(group1);
		env.forceInstall();

		// edit the document
		doc1.replace(7, 6, "INE-PLANTA");

		assertEquals(group1, "MARGARINE-PLANTA");
		assertFalse(isExit[0]);
		Assert.assertEquals("	MARGARINE-PLANTA" +
				"Versprich mir, Heinrich!", doc1.get(0, 41));
//		assertUnchanged(group1); // would fail, since it was changed outside
	}

	@Test
	public void testOverlappingDelete() throws BadLocationException {
		// a change partially touches a linked position, but also "in-between" text
		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");
		LinkedModeModel env= new LinkedModeModel();
		final boolean[] isExit= { false } ;
		env.addLinkingListener(new LinkedAdapter() {
			@Override
			public void left(LinkedModeModel environment, int flags) {
				isExit[0]= true;
			}
		});
		env.addGroup(group1);
		env.forceInstall();

		// edit the document
		doc1.replace(7, 6, "");

		assertEquals(group1, "MARGAR");
		assertFalse(isExit[0]);
		Assert.assertEquals("	MARGAR" +
				"Versprich mir, Heinrich!", doc1.get(0, 31));
//		assertUnchanged(group1); // would fail, since it was changed outside
	}

	@Test
	public void testIllegalChange1() throws BadLocationException {
		// linked mode does not exit if the documents change outside the linked
		// positions, but it does exit if a change invalidates the constraints
		// on the positions (complete disjointness, no touching positions)

		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");

		LinkedModeModel env= new LinkedModeModel();
		final boolean[] isExit= { false } ;
		env.addLinkingListener(new LinkedAdapter() {
			@Override
			public void left(LinkedModeModel environment, int flags) {
				isExit[0]= true;
			}
		});
		env.addGroup(group1);
		env.forceInstall();

		// edit the document
		doc1.replace(1, 73, "");

		assertTrue(isExit[0]);
	}

	@Test
	public void testIllegalChange2() throws BadLocationException {
		// linked mode does not exit if the documents change outside the linked
		// positions, but it does exit if a change invalidates the constraints
		// on the positions (complete disjointness, no touching positions)

		IDocument doc1= new Document(GARTEN1);

		// set up linked mode
		LinkedPositionGroup group1= new LinkedPositionGroup();
		createLinkedPositions(group1, doc1, "MARGARETE");

		LinkedPositionGroup group2= new LinkedPositionGroup();
		createLinkedPositions(group2, doc1, "FAUST");

		LinkedModeModel env= new LinkedModeModel();
		final boolean[] isExit= { false } ;
		env.addLinkingListener(new LinkedAdapter() {
			@Override
			public void left(LinkedModeModel environment, int flags) {
				isExit[0]= true;
			}
		});
		env.addGroup(group1);
		env.addGroup(group2);
		env.forceInstall();

		// edit the document
		doc1.replace(9, 35, "");

		assertTrue(isExit[0]);
	}

	private void assertEquals(LinkedPositionGroup group, String expected) throws BadLocationException {
		LinkedPosition[] positions= group.getPositions();
		for (LinkedPosition pos : positions) {
			if (!pos.isDeleted())
				Assert.assertEquals(expected, pos.getContent());
		}
	}

	private void assertUnchanged(LinkedPositionGroup actual1) throws BadLocationException {
		assertUnchanged(actual1, new LinkedPositionGroup());
	}

	private void assertUnchanged(LinkedPositionGroup actual1, LinkedPositionGroup actual2) throws BadLocationException {
		LinkedPosition[] exp= fPositions.toArray(new LinkedPosition[0]);
		LinkedPosition[] act1= actual1.getPositions();
		LinkedPosition[] act2= actual2.getPositions();
		LinkedPosition[] act= new LinkedPosition[act1.length + act2.length];
		System.arraycopy(act1, 0, act, 0, act1.length);
		System.arraycopy(act2, 0, act, act1.length, act2.length);
		Arrays.sort(act, new PositionComparator());
		Arrays.sort(exp, new PositionComparator());

		Assert.assertEquals(exp.length, act.length);

		LinkedPosition e_prev= null, a_prev= null;
		for (int i= 0; i <= exp.length; i++) {
			LinkedPosition e_next= i == exp.length ? null : exp[i];
			LinkedPosition a_next= i == exp.length ? null : act[i];

			IDocument e_doc= e_prev != null ? e_prev.getDocument() : e_next.getDocument();
			if (e_next != null && e_next.getDocument() != e_doc) {
				// split at document boundaries
				Assert.assertEquals(getContentBetweenPositions(e_prev, null), getContentBetweenPositions(a_prev, null));
				Assert.assertEquals(getContentBetweenPositions(null, e_next), getContentBetweenPositions(null, a_next));
			} else {
				Assert.assertEquals(getContentBetweenPositions(e_prev, e_next), getContentBetweenPositions(a_prev, a_next));
			}

			e_prev= e_next;
			a_prev= a_next;
		}
	}

	private String getContentBetweenPositions(LinkedPosition p1, LinkedPosition p2) throws BadLocationException {
		if (p1 == null && p2 == null)
			return null;
		if (p1 == null)
			p1= new LinkedPosition(p2.getDocument(), 0, 0);

		if (p2 == null)
			p2= new LinkedPosition(p1.getDocument(), p1.getDocument().getLength(), 0);

		IDocument document= p1.getDocument();

		int offset= p1.getOffset() + p1.getLength();
		int length= p2.getOffset() - offset;

		return document.get(offset, length);
	}


	@Before
	public void setUp() {
		fPositions.clear();
		fDocumentMap.clear();
	}

	/*
	 * Returns a test group on a copy of the document
	 */
	private void createLinkedPositions(LinkedPositionGroup group, IDocument doc, String substring) throws BadLocationException {
		String text= doc.get();

		IDocument original= getOriginal(doc);
		if (original == null) {
			original= new Document(text);
			putOriginal(doc, original);
		}


		for (int offset= text.indexOf(substring); offset != -1; offset= text.indexOf(substring, offset + 1)) {
			group.addPosition(new LinkedPosition(doc, offset, substring.length(), LinkedPositionGroup.NO_STOP));
			fPositions.add(new LinkedPosition(original, offset, substring.length()));
		}

	}

	private void putOriginal(IDocument doc, IDocument original) {
		fDocumentMap.add(new IDocument[] { doc, original });
	}

	private IDocument getOriginal(IDocument doc) {
		for (IDocument[] docs : fDocumentMap) {
			if (docs[0] == doc)
				return docs[1];
		}
		return null;
	}

	private static final String GARTEN1=
		"	MARGARETE:\n" +
		"	Versprich mir, Heinrich!\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Was ich kann!\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Nun sag, wie hast du\'s mit der Religion?\n" +
		"	Du bist ein herzlich guter Mann,\n" +
		"	Allein ich glaub, du haltst nicht viel davon.\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Las das, mein Kind! Du fuhlst, ich bin dir gut;\n" +
		"	Fur meine Lieben lies\' ich Leib und Blut,\n" +
		"	Will niemand sein Gefuhl und seine Kirche rauben.\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Das ist nicht recht, man mus dran glauben.\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Mus man?\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Ach! wenn ich etwas auf dich konnte! Du ehrst auch nicht die heil\'gen Sakramente.\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Ich ehre sie.\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Doch ohne Verlangen. Zur Messe, zur Beichte bist du lange nicht gegangen.\n" +
		"	Glaubst du an Gott?\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Mein Liebchen, wer darf sagen: Ich glaub an Gott?\n" +
		"	Magst Priester oder Weise fragen,\n" +
		"	Und ihre Antwort scheint nur Spott\n" +
		"	uber den Frager zu sein.\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	So glaubst du nicht?\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Mishor mich nicht, du holdes Angesicht!\n" +
		"	Wer darf ihn nennen?\n" +
		"	Und wer bekennen:\n" +
		"	\"Ich glaub ihn!\"?\n" +
		"	Wer empfinden,\n" +
		"	Und sich unterwinden\n" +
		"	Zu sagen: \"Ich glaub ihn nicht!\"?\n" +
		"	Der Allumfasser,\n" +
		"	Der Allerhalter,\n" +
		"	Fast und erhalt er nicht\n" +
		"	Dich, mich, sich selbst?\n" +
		"	Wolbt sich der Himmel nicht da droben?\n" +
		"	Liegt die Erde nicht hier unten fest?\n" +
		"	Und steigen freundlich blickend\n" +
		"	Ewige Sterne nicht herauf?\n" +
		"	Schau ich nicht Aug in Auge dir,\n" +
		"	Und drangt nicht alles\n" +
		"	Nach Haupt und Herzen dir,\n" +
		"	Und webt in ewigem Geheimnis\n" +
		"	Unsichtbar sichtbar neben dir?\n" +
		"	Erfull davon dein Herz, so gros es ist,\n" +
		"	Und wenn du ganz in dem Gefuhle selig bist,\n" +
		"	Nenn es dann, wie du willst,\n" +
		"	Nenn\'s Gluck! Herz! Liebe! Gott\n" +
		"	Ich habe keinen Namen\n" +
		"	Dafur! Gefuhl ist alles;\n" +
		"	Name ist Schall und Rauch,\n" +
		"	Umnebelnd Himmelsglut.\n";

	private static final String GARTEN2=
		"	MARGARETE:\n" +
		"	Das ist alles recht schon und gut;\n" +
		"	Ungefahr sagt das der Pfarrer auch,\n" +
		"	Nur mit ein bischen andern Worten.\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Es sagen\'s allerorten\n" +
		"	Alle Herzen unter dem himmlischen Tage,\n" +
		"	Jedes in seiner Sprache;\n" +
		"	Warum nicht ich in der meinen?\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Wenn man\'s so hort, mocht\'s leidlich scheinen,\n" +
		"	Steht aber doch immer schief darum;\n" +
		"	Denn du hast kein Christentum.\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Liebs Kind!\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Es tut mir lange schon weh, Das ich dich in der Gesellschaft seh.\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Wieso?\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Der Mensch, den du da bei dir hast, Ist mir in tiefer innrer Seele verhast;\n" +
		"	Es hat mir in meinem Leben\n" +
		"	So nichts einen Stich ins Herz gegeben\n" +
		"	Als des Menschen widrig Gesicht.\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Liebe Puppe, furcht ihn nicht!\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Seine Gegenwart bewegt mir das Blut.\n" +
		"	Ich bin sonst allen Menschen gut;\n" +
		"	Aber wie ich mich sehne, dich zu schauen,\n" +
		"	Hab ich vor dem Menschen ein heimlich Grauen,\n" +
		"	Und halt ihn fur einen Schelm dazu!\n" +
		"	Gott verzeih mir\'s, wenn ich ihm unrecht tu!\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Es mus auch solche Kauze geben.\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Wollte nicht mit seinesgleichen leben!\n" +
		"	Kommt er einmal zur Tur herein,\n" +
		"	Sieht er immer so spottisch drein\n" +
		"	Und halb ergrimmt;\n" +
		"	Man sieht, das er an nichts keinen Anteil nimmt;\n" +
		"	Es steht ihm an der Stirn geschrieben,\n" +
		"	Das er nicht mag eine Seele lieben.\n" +
		"	Mir wird\'s so wohl in deinem Arm,\n" +
		"	So frei, so hingegeben warm,\n" +
		"	Und seine Gegenwart schnurt mir das Innre zu.\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Du ahnungsvoller Engel du!\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Das ubermannt mich so sehr,\n" +
		"	Das, wo er nur mag zu uns treten,\n" +
		"	Mein ich sogar, ich liebte dich nicht mehr.\n" +
		"	Auch, wenn er da ist, konnt ich nimmer beten,\n" +
		"	Und das frist mir ins Herz hinein;\n" +
		"	Dir, Heinrich, mus es auch so sein.\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Du hast nun die Antipathie!\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Ich mus nun fort.\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Ach kann ich nie Ein Stundchen ruhig dir am Busen hangen\n" +
		"	Und Brust an Brust und Seel in Seele drangen?\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Ach wenn ich nur alleine schlief!\n" +
		"	Ich lies dir gern heut nacht den Riegel offen;\n" +
		"	Doch meine Mutter schlaft nicht tief,\n" +
		"	Und wurden wir von ihr betroffen,\n" +
		"	Ich war gleich auf der Stelle tot!\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Du Engel, das hat keine Not.\n" +
		"	Hier ist ein Flaschchen!\n" +
		"	Drei Tropfen nur In ihren Trank umhullen\n" +
		"	Mit tiefem Schlaf gefallig die Natur.\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Was tu ich nicht um deinetwillen?\n" +
		"	Es wird ihr hoffentlich nicht schaden!\n" +
		"	 \n" +
		"	FAUST:\n" +
		"	Wurd ich sonst, Liebchen, dir es raten?\n" +
		"	 \n" +
		"	MARGARETE:\n" +
		"	Seh ich dich, bester Mann, nur an,\n" +
		"	Weis nicht, was mich nach deinem Willen treibt,\n" +
		"	Ich habe schon so viel fur dich getan,\n" +
		"	Das mir zu tun fast nichts mehr ubrigbleibt.";

	private static class LinkedAdapter implements ILinkedModeListener {
		@Override
		public void left(LinkedModeModel environment, int flags) {}
		@Override
		public void suspend(LinkedModeModel environment) {}
		@Override
		public void resume(LinkedModeModel environment, int flags) {}
	}

	public class PositionComparator implements Comparator<LinkedPosition> {

		@Override
		public int compare(LinkedPosition p1, LinkedPosition p2) {
			IDocument d1= p1.getDocument();
			IDocument d2= p2.getDocument();

			if (d1 == d2)
				// sort by offset inside the same document
				return p1.getOffset() - p2.getOffset();
			return getIndex(d1) - getIndex(d2);
		}

		private int getIndex(IDocument doc) {
			int i= 0;
			for (Iterator<IDocument[]> it= fDocumentMap.iterator(); it.hasNext(); i++) {
				IDocument[] docs= it.next();
				if (docs[0] == doc || docs[1] == doc)
					return i;
			}
			return -1;
		}
	}

}
