/*******************************************************************************
 * Copyright (c) 2008, 2009 Oracle. 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:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.utility.tests.internal.synchronizers;

import junit.framework.TestCase;

import org.eclipse.jpt.utility.Command;
import org.eclipse.jpt.utility.internal.ClassTools;
import org.eclipse.jpt.utility.internal.CompositeException;
import org.eclipse.jpt.utility.internal.SynchronizedBoolean;
import org.eclipse.jpt.utility.internal.synchronizers.Synchronizer;
import org.eclipse.jpt.utility.internal.synchronizers.SynchronousSynchronizer;

@SuppressWarnings("nls")
public class SynchronousSynchronizerTests extends TestCase {
	PrimaryModel1 primaryModel1;
	SecondaryModel1 secondaryModel1;
	Command command1;
	Synchronizer synchronizer1;

	PrimaryModel2 primaryModel2;
	SecondaryModel2 secondaryModel2;
	Command command2;
	Synchronizer synchronizer2;

	public SynchronousSynchronizerTests(String name) {
		super(name);
	}

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		this.primaryModel1 = new PrimaryModel1();
		this.secondaryModel1 = new SecondaryModel1(this.primaryModel1);
		this.command1 = new SynchronizeSecondaryModelCommand1(this.secondaryModel1);
		this.synchronizer1 = new SynchronousSynchronizer(this.command1);
		this.primaryModel1.setSynchronizer(this.synchronizer1);

		this.primaryModel2 = new PrimaryModel2();
		this.secondaryModel2 = new SecondaryModel2(this.primaryModel2);
		this.command2 = new SynchronizeSecondaryModelCommand2(this.primaryModel2, this.secondaryModel2);
		this.synchronizer2 = new SynchronousSynchronizer(this.command2);
		this.primaryModel2.setSynchronizer(this.synchronizer2);
	}

	public void testInitialization() {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
	}

	public void testToString() {
		assertNotNull(this.synchronizer1.toString());
	}

	public void testChange() {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		this.primaryModel1.setCount(7);
		assertEquals(14, this.secondaryModel1.getDoubleCount());
	}

	public void testStart() {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		this.primaryModel1.setSynchronizer(Synchronizer.Null.instance());
		this.primaryModel1.setCount(7);
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		this.primaryModel1.setSynchronizer(this.synchronizer1);
		assertEquals(14, this.secondaryModel1.getDoubleCount());
	}

	public void testStop() {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		this.primaryModel1.dispose();
		this.primaryModel1.setCount(7);
		assertEquals(4, this.secondaryModel1.getDoubleCount());
	}

	public void testDoubleStart() {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		boolean exCaught = false;
		try {
			this.primaryModel1.startSynchronizer();
			fail();
		} catch (IllegalStateException ex) {
			exCaught = true;
		}
		assertTrue(exCaught);
		this.primaryModel1.setCount(7);
		assertEquals(14, this.secondaryModel1.getDoubleCount());
	}

	public void testDoubleStop() {
		assertEquals(4, this.secondaryModel1.getDoubleCount());
		this.primaryModel1.dispose();
		boolean exCaught = false;
		try {
			this.primaryModel1.dispose();
			fail();
		} catch (IllegalStateException ex) {
			exCaught = true;
		}
		assertTrue(exCaught);
		this.primaryModel1.setCount(7);
		assertEquals(4, this.secondaryModel1.getDoubleCount());
	}

	public void testRecursiveChange() {
		assertEquals(4, this.secondaryModel2.getDoubleCount());
		this.primaryModel2.setCount(7);
		assertEquals(10, this.primaryModel2.getCountPlus3());
		assertEquals(14, this.secondaryModel2.getDoubleCount());
		assertEquals(20, this.secondaryModel2.getDoubleCountPlus3());
	}

	/**
	 * Call #stop() from another thread.
	 * Verify that no further synchronizations occur.
	 * Verify the call to #stop() does not return until the pending
	 * synchronization is complete (must set {@link #DEBUG} to true and
	 * look at the console).
	 * 
	 * ticks:
	 * 0 - start "sync" thread (which will sleep for 1 tick);
	 *      start "stop" thread (which will sleep for 2 ticks)
	 * 1 - "sync" thread wakes up and calls PrimaryModel1.setCount(int)
	 *      which triggers call to Synchronizer.synchronize() to begin
	 *      synchronization of SecondaryModel (which will run for 2 ticks;
	 *      i.e. it will finish on tick 3)
	 * 2 - "stop" thread wakes up and calls Synchronizer.stop() and should
	 *      wait until synchronization is complete
	 * 3 - synchronization completes first execution and should stop;
	 *      "stop" thread should run to completion once the synchronization has stopped
	 */
	public void testCallStopFromAnotherThread() throws Exception {
		log("=====" + this.getName() + "=====");
		PrimaryModel2 primaryModel3 = new PrimaryModel2();
		// a synchronize will occur here:
		SecondaryModel3 secondaryModel3 = new SecondaryModel3(primaryModel3);
		Command command3 = new SynchronizeSecondaryModelCommand2(primaryModel3, secondaryModel3);
		Synchronizer synchronizer3 = new SynchronousSynchronizer(command3);
		// another synchronize will occur here:
		primaryModel3.setSynchronizer(synchronizer3);
		secondaryModel3.setTicks(2);

		assertEquals(2, primaryModel3.getCount());
		assertEquals(5, primaryModel3.getCountPlus3());
		assertEquals(4, secondaryModel3.getDoubleCount());
		assertEquals(10, secondaryModel3.getDoubleCountPlus3());

		Thread syncThread = this.buildTriggerSynchronizeThread(primaryModel3, 1);
		Thread stopThread = this.buildStopThread(synchronizer3, 2);

		log("ALL threads start");
		stopThread.start();
		syncThread.start();

		stopThread.join();
		syncThread.join();

		// 'doubleCount' is synchronized; but the synchronization is stopped
		// while that is happening (by the 'stopThread'), so 'doubleCountPlus3'
		// does not get synchronized
		assertEquals(7, primaryModel3.getCount());
		assertEquals(10, primaryModel3.getCountPlus3());
		assertEquals(14, secondaryModel3.getDoubleCount());

		// this does not get updated because it would've been updated by the
		// recursive call to #synchronize(), but by that time #stop() had been called
		assertEquals(10, secondaryModel3.getDoubleCountPlus3());
	}

	private Thread buildTriggerSynchronizeThread(final PrimaryModel2 primaryModel, final long ticks) {
		return new Thread("trigger sync") {
			@Override
			public void run() {
				delay(ticks);
				primaryModel.setCount(7);
			}
		};
	}

	private Thread buildStopThread(final Synchronizer synchronizer, final long ticks) {
		return new Thread("stop") {
			@Override
			public void run() {
				delay(ticks);
				log("STOP thread Synchronizer.stop()");
				synchronizer.stop();
				log("STOP thread stop");
			}
		};
	}

	/**
	 * Code cloned from {@link #testStopCalledFromAnotherThread()}.
	 * 
	 * Interrupt the "stop" thread while it is waiting for the "synch" thread to finish.
	 * Verify that no further synchronizations occur.
	 * Verify the call to #stop() returns *before*
	 * synchronization is complete (must set {@link #DEBUG} to true and
	 * look at the console).
	 * 
	 * ticks:
	 * 0 - start "sync" thread (which will sleep for 1 tick);
	 *      start "stop" thread (which will sleep for 2 ticks);
	 *      start "interrupt" thread (which will sleep for 3 ticks)
	 * 1 - "sync" thread wakes up and calls PrimaryModel1.setCount(int)
	 *      which triggers call to Synchronizer.synchronize() to begin
	 *      synchronization of SecondaryModel (which will run for 3 ticks;
	 *      i.e. it will finish on tick 4)
	 * 2 - "stop" thread wakes up and calls Synchronizer.stop() and should
	 *      wait until it is interrupted
	 * 3 - "interrupt" thread wakes up and interrupts "stop" thread;
	 *       both will run to completion at that point
	 * 4 - synchronization completes first execution and should stop since the
	 *      "stop" thread, before it was interrupted, told the "synch" thread to stop
	 */
	public void testInterruptStopThread() throws Exception {
		log("=====" + this.getName() + "=====");
		PrimaryModel2 primaryModel3 = new PrimaryModel2();
		// a synchronize will occur here:
		SecondaryModel3 secondaryModel3 = new SecondaryModel3(primaryModel3);
		Command command3 = new SynchronizeSecondaryModelCommand2(primaryModel3, secondaryModel3);
		Synchronizer synchronizer3 = new SynchronousSynchronizer(command3);
		// another synchronize will occur here:
		primaryModel3.setSynchronizer(synchronizer3);
		secondaryModel3.setTicks(3);

		assertEquals(2, primaryModel3.getCount());
		assertEquals(5, primaryModel3.getCountPlus3());
		assertEquals(4, secondaryModel3.getDoubleCount());
		assertEquals(10, secondaryModel3.getDoubleCountPlus3());

		Thread syncThread = this.buildTriggerSynchronizeThread(primaryModel3, 1);
		Thread stopThread = this.buildStopThread(synchronizer3, 2);
		Thread interruptThread = this.buildInterruptThread(stopThread, 3);

		log("ALL threads start");
		stopThread.start();
		syncThread.start();
		interruptThread.start();

		stopThread.join();
		syncThread.join();
		interruptThread.join();

		// 'doubleCount' is synchronized; but the synchronization is stopped
		// while that is happening (by the 'stopThread'), so 'doubleCountPlus3'
		// does not get synchronized
		assertEquals(7, primaryModel3.getCount());
		assertEquals(10, primaryModel3.getCountPlus3());
		assertEquals(14, secondaryModel3.getDoubleCount());

		// this does not get updated because it would've been updated by the
		// recursive call to #synchronize(), but by that time #stop() had been called
		assertEquals(10, secondaryModel3.getDoubleCountPlus3());
	}

	/**
	 * Code cloned from {@link #testStopCalledFromAnotherThread()}.
	 * 
	 * Interrupt the "sync" thread while it is synchronizing, cutting short the synchronization.
	 * Verify that no further synchronizations occur.
	 * Verify the call to #stop() does not return until the pending
	 * synchronization is stops after it is interrupted (must set {@link #DEBUG} to true and
	 * look at the console).
	 * 
	 * ticks:
	 * 0 - start "sync" thread (which will sleep for 1 tick)
	 *      start "stop" thread (which will sleep for 2 ticks)
	 *      start "interrupt" thread (which will sleep for 3 ticks)
	 * 1 - "sync" thread wakes up and calls PrimaryModel1.setCount(int)
	 *      which triggers call to Synchronizer.synchronize() to begin
	 *      synchronization of SecondaryModel (which will run for 4 ticks;
	 *      i.e. it will finish on tick 5)
	 * 2 - "stop" thread wakes up and calls Synchronizer.stop() and should
	 *      wait until the synchronization is interrupted
	 * 3 - "interrupt" thread wakes up and interrupts "sync" thread;
	 *      the "interrupt" thread runs to completion, while the "sync" thread keeps
	 *      going for another tick before it stops in "mid-synchronize"
	 * 4 - the "sync" thread acknowledges the interrupt and stops in
	 *      "mid-synchronize"; it will stop since the "stop" thread told it to at tick 2;
	 *      the "sync" and "stop" threads run to completion
	 */
	public void testInterruptSyncThread() throws Exception {
		log("=====" + this.getName() + "=====");
		PrimaryModel2 primaryModel3 = new PrimaryModel2();
		// a synchronize will occur here:
		SecondaryModel3 secondaryModel3 = new SecondaryModel3(primaryModel3);
		Command command3 = new SynchronizeSecondaryModelCommand2(primaryModel3, secondaryModel3);
		Synchronizer synchronizer3 = new SynchronousSynchronizer(command3);
		// another synchronize will occur here:
		primaryModel3.setSynchronizer(synchronizer3);
		secondaryModel3.setTicks(4);

		assertEquals(2, primaryModel3.getCount());
		assertEquals(5, primaryModel3.getCountPlus3());
		assertEquals(4, secondaryModel3.getDoubleCount());
		assertEquals(10, secondaryModel3.getDoubleCountPlus3());

		Thread syncThread = this.buildTriggerSynchronizeThread(primaryModel3, 1);
		Thread stopThread = this.buildStopThread(synchronizer3, 2);
		Thread interruptThread = this.buildInterruptThread(syncThread, 3);

		log("ALL threads start");
		stopThread.start();
		syncThread.start();
		interruptThread.start();

		stopThread.join();
		syncThread.join();
		interruptThread.join();

		assertEquals(7, primaryModel3.getCount());
		assertEquals(10, primaryModel3.getCountPlus3());

		// none of the secondary model is synchronized because the synchronize()
		// method was interrupted before any synchronization had occurred
		assertEquals(4, secondaryModel3.getDoubleCount());
		assertEquals(10, secondaryModel3.getDoubleCountPlus3());
	}

	private Thread buildInterruptThread(final Thread thread, final long ticks) {
		return new Thread("interrupt") {
			@Override
			public void run() {
				delay(ticks);
				log("INTERRUPT thread Thread.interrupt()");
				thread.interrupt();
			}
		};
	}

	/**
	 * Call #stop() during a long-running "synchronize"; then call #start()
	 * while the #stop() is waiting for the "synchronize" to complete.
	 * 
	 * ticks:
	 * 0 - start "sync" thread (which will sleep for 1 tick)
	 *      start "stop" thread (which will sleep for 2 ticks)
	 *      start "start" thread (which will sleep for 3 ticks)
	 * 1 - "sync" thread wakes up and calls Synchronizer.synchronize() to begin
	 *      synchronization (which will run for 3 ticks; i.e. it will finish on tick 4)
	 * 2 - "stop" thread wakes up and calls Synchronizer.stop() and should
	 *      wait until the synchronization is finished (i.e. tick 4)
	 * 3 - "start" thread wakes up and calls Synchronizer.start()
	 *      which will throw an exception
	 * 4 - the "sync" thread finishes execution;
	 *      it will stop since the "stop" thread told it to at tick 2;
	 *      the "sync" and "stop" threads run to completion
	 */
	public void testCallStartDuringStop() throws Exception {
		log("=====" + this.getName() + "=====");
		DelayCommand command = this.buildDelayCommand(3);
		Synchronizer synchronizer = new SynchronousSynchronizer(command);
		synchronizer.start();

		Thread syncThread = this.buildSynchronizeThread(synchronizer, 1);
		Thread stopThread = this.buildStopThread(synchronizer, 2);
		SynchronizedBoolean exCaught = new SynchronizedBoolean(false);
		Thread startThread = this.buildStartThread(synchronizer, 3, exCaught);

		log("ALL threads start");
		syncThread.start();
		stopThread.start();
		startThread.start();

		syncThread.join();
		stopThread.join();
		startThread.join();

		assertTrue(exCaught.getValue());
		assertEquals(2, command.count);
	}

	private DelayCommand buildDelayCommand(float ticks) {
		return new DelayCommand(ticks);
	}

	class DelayCommand implements Command {
		final float ticks;
		boolean first = true;
		int count = 0;

		DelayCommand(float ticks) {
			super();
			this.ticks = ticks;
		}

		public void execute() {
			this.count++;
			// do nothing for the first call (from #start())
			if (this.first) {
				log("EXEC first");
				this.first = false;
				return;
			}
			log("EXEC start " + this.count);
			delay(this.ticks);
			log("EXEC stop " + this.count);
		}

	}

	private Thread buildStartThread(final Synchronizer synchronizer, final long ticks, final SynchronizedBoolean exCaught) {
		return new Thread("start") {
			@Override
			public void run() {
				delay(ticks);
				log("START thread Synchronizer.start()");
				try {
					synchronizer.start();
				} catch (IllegalStateException ex) {
					exCaught.setTrue();
					log("START thread exception");
				}
				log("START thread stop");
			}
		};
	}

	private Thread buildSynchronizeThread(final Synchronizer synchronizer, final long ticks) {
		return new Thread("synchronize") {
			@Override
			public void run() {
				delay(ticks);
				log("SYNC thread Synchronizer.synchronize()");
				synchronizer.synchronize();
				log("SYNC thread stop");
			}
		};
	}

	public void testException() throws Exception {
		BogusCommand command = new BogusCommand();
		Synchronizer synchronizer = new SynchronousSynchronizer(command);
		synchronizer.start();

		try {
			synchronizer.synchronize();
		} catch (NullPointerException ex) {
			// ignore
		}

		boolean exCaught = false;
		try {
			// we used to hang here, before we began handling exceptions
			synchronizer.stop();
			fail();
		} catch (CompositeException ex) {
			assertEquals(1, ex.getExceptions().length);
			exCaught = true;
		}
		assertTrue(exCaught);
		// start + synchronize
		assertEquals(2, command.count);
	}

	public class BogusCommand implements Command {
		int count = 0;
		public void execute() {
			this.count++;
			if (this.count > 1) {
				throw new NullPointerException();
			}
		}
	}


	// ********** synchronize commands **********
	public static class SynchronizeSecondaryModelCommand1 implements Command {
		private final SecondaryModel1 secondaryModel;

		public SynchronizeSecondaryModelCommand1(SecondaryModel1 secondaryModel) {
			super();
			this.secondaryModel = secondaryModel;
		}

		public void execute() {
			this.secondaryModel.synchronize();
		}

	}

	/**
	 * the primary model (subclass) has to synchronize with itself (superclass)
	 */
	public static class SynchronizeSecondaryModelCommand2 extends SynchronizeSecondaryModelCommand1 {
		private final PrimaryModel2 primaryModel;

		public SynchronizeSecondaryModelCommand2(PrimaryModel2 primaryModel, SecondaryModel2 secondaryModel) {
			super(secondaryModel);
			this.primaryModel = primaryModel;
		}

		@Override
		public void execute() {
			super.execute();
			this.primaryModel.synchronize();
		}

	}

	// ********** primary models **********
	/**
	 * this object will call the synchronizer whenever its count changes,
	 * allowing interested parties to synchronize with the change
	 */
	public static class PrimaryModel1 {
		protected Synchronizer synchronizer;
		protected int count = 2;

		public PrimaryModel1() {
			super();
			this.setSynchronizer_(Synchronizer.Null.instance());
		}

		public int getCount() {
			return this.count;
		}
		public void setCount(int count) {
			if (count != this.count) {
				this.count = count;
				this.stateChanged();
			}
		}

		protected void stateChanged() {
			this.synchronizer.synchronize();
		}

		public void setSynchronizer(Synchronizer synchronizer) {
			if (synchronizer == null) {
				throw new NullPointerException();
			}
			this.synchronizer.stop();
			this.setSynchronizer_(synchronizer);
		}
			
		protected void setSynchronizer_(Synchronizer synchronizer) {
			this.synchronizer = synchronizer;
			this.synchronizer.start();
		}

		public void startSynchronizer() {
			this.synchronizer.start();  // this should cause an exception
		}
		public void dispose() {
			this.synchronizer.stop();
		}

		@Override
		public String toString() {
			StringBuilder sb = new StringBuilder();
			sb.append(ClassTools.toStringClassNameForObject(this));
			sb.append('(');
			this.toString(sb);
			sb.append(')');
			return sb.toString();
		}
		public void toString(StringBuilder sb) {
			sb.append("count=");
			sb.append(this.count);
		}

	}

	/**
	 * This model synchronizes with itself, triggering a recursive synchronization
	 * with the change. Whenever the [inherited] 'count' changes, 'countPlus3'
	 * is updated appropriately and another synchronize is initiated if appropriate.
	 */
	public static class PrimaryModel2 extends PrimaryModel1 {
		private int countPlus3 = 0;

		public PrimaryModel2() {
			super();
			this.countPlus3 = this.count + 3;
		}

		public int getCountPlus3() {
			return this.countPlus3;
		}
		protected void setCountPlus3(int countPlus3) {
			if (countPlus3 != this.countPlus3) {
				this.countPlus3 = countPlus3;
				this.stateChanged();
			}
		}

		// synchronize with itself, so to speak
		public void synchronize() {
			this.setCountPlus3(this.count + 3);
		}

		@Override
		public void toString(StringBuilder sb) {
			super.toString(sb);
			sb.append(", countPlus3=");
			sb.append(this.countPlus3);
		}

	}

	// ********** secondary models **********
	/**
	 * This dependent object updates its 'doubleCount' whenever the
	 * PrimaryModel1's 'count' changes, via the 'synchronizer'.
	 */
	public static class SecondaryModel1 {
		protected final PrimaryModel1 primaryModel;
		protected int doubleCount = 0;

		public SecondaryModel1(PrimaryModel1 primaryModel) {
			super();
			this.primaryModel = primaryModel;
			this.synchronize();
		}

		public void synchronize() {
			this.doubleCount = this.primaryModel.getCount() * 2;
		}

		public int getDoubleCount() {
			return this.doubleCount;
		}

		@Override
		public String toString() {
			StringBuilder sb = new StringBuilder();
			sb.append(ClassTools.toStringClassNameForObject(this));
			sb.append('(');
			this.toString(sb);
			sb.append(')');
			return sb.toString();
		}
		public void toString(StringBuilder sb) {
			sb.append("doubleCount=");
			sb.append(this.doubleCount);
		}

	}

	public static class SecondaryModel2 extends SecondaryModel1 {
		private int doubleCountPlus3 = 0;

		public SecondaryModel2(PrimaryModel2 extendedPrimaryModel) {
			super(extendedPrimaryModel);
		}

		protected PrimaryModel2 getExtendedPrimaryModel() {
			return (PrimaryModel2) this.primaryModel;
		}

		@Override
		public void synchronize() {
			super.synchronize();
			int temp = this.getExtendedPrimaryModel().getCountPlus3() * 2;
			if (this.doubleCountPlus3 != temp) {
				this.doubleCountPlus3 = temp;
			}
		}

		public int getDoubleCountPlus3() {
			return this.doubleCountPlus3;
		}

		@Override
		public void toString(StringBuilder sb) {
			super.toString(sb);
			sb.append(", doubleCountPlus3=");
			sb.append(this.doubleCountPlus3);
		}

	}

	/**
	 * Allow the time required to synchronize to be specified.
	 * A (non-delayed) synchronize will execute before we have a chance to
	 * change the tick count. (It is called in the SecondaryModel1 constructor.)
	 */
	public static class SecondaryModel3 extends SecondaryModel2 {
		private long ticks = 0;
		public SecondaryModel3(PrimaryModel2 primaryModel) {
			super(primaryModel);
		}

		public void setTicks(long ticks) {
			this.ticks = ticks;
		}

		@Override
		public void synchronize() {
			// don't log anything until 'ticks' is set
			if (this.ticks == 0) {
				super.synchronize();
			} else {
				log("SYNC thread start - sync duration will be: " + this.ticks + " ticks");
				try {
					delay_(this.ticks);
				} catch (InterruptedException ex) {
					log("SYNC thread interrupted");
					delay(1);
					return;  // stop synchronize (i.e. don't call super.synchronize())
				}
				super.synchronize();
				log("SYNC thread stop");
			}
		}

	}

	public void testDEBUG() {
		assertFalse(DEBUG);
	}

	public static final boolean DEBUG = false;
	public static void log(String message) {
		if (DEBUG) {
			log_(message);
		}
	}

	private static void log_(String message) {
		System.out.print(timestamp());
		System.out.print(' ');
		System.out.print(message);
		System.out.println();
	}

	public static String timestamp() {
		return String.valueOf((System.currentTimeMillis() % 10000) / 1000f);
	}

	public static void delay(float ticks) {
		try {
			delay_(ticks);
		} catch (InterruptedException ex) {
			// just stop everything and return
			log("INTERRUPT");
			return;
		}
	}

	public static void delay_(float ticks) throws InterruptedException {
		// a tenth of second per tick should work...
		long milliseconds = (long) (ticks * 100);
		long stop = System.currentTimeMillis() + milliseconds;
		long remaining = milliseconds;
		while (remaining > 0L) {
			Thread.sleep(remaining);
			remaining = stop - System.currentTimeMillis();
		}
	}

}
