package jforex.test;

import com.dukascopy.api.*;

public class HistoryThreadTest4 implements IStrategy {

	private IConsole console;
	private IHistory history;
	private IEngine engine;

	@Configurable("patience (in seconds)")
	public int patience = 3;

	@Override
	public void onStart(IContext context) throws JFException {
		this.console = context.getConsole();
		this.history = context.getHistory();
		this.engine = context.getEngine();

		print("test success (execute immediately)");

		boolean onTime1= launchTask(new IFunction() {

			@Override
			public void execute() throws InterruptedException {
				try {
					console.getOut().println(" last tick: " + history.getLastTick(Instrument.EURUSD) 
							+ " active order count: " + engine.getOrders().size());					
				} catch (JFException e) {
					console.getErr().println("-1 " + e);
				}
			}

		}, patience);

		print("test fail (execute for patience + 2 secs)");

		boolean onTime2 = launchTask(new IFunction() {

			@Override
			public void execute() throws InterruptedException {
				for (int i = 0; i < patience + 3; i++) {
					Thread.sleep(1000);
					try {
						console.getOut().println(i + " last tick: " + history.getLastTick(Instrument.EURUSD) 
								+ " active order count: " + engine.getOrders().size());
					} catch (JFException e) {
						console.getErr().println("-1 " + e);
					}
				}
			}

		}, patience);

		print("Task 1 on time: "+onTime1 +". Task 2 on time: " + onTime2);
		context.stop();

	}

	private interface IFunction {
		public void execute() throws InterruptedException;
	}

	/**
	 * Launches a task in a separate thread with expiry time
	 * 
	 * @param function
	 *            task
	 * @param expiryTime
	 *            expiry time in seconds
	 * @return true if task succeeded to execute before the expiration time
	 */
	private boolean launchTask(final IFunction function, int expiryTime) {

		long startTime = System.currentTimeMillis();
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					function.execute();
				} catch (InterruptedException e) {
					console.getErr().println(Thread.currentThread().getName() + " got interrupted!");
				}
			}
		});
		t.start();

		// loop until MessageLoop thread exits
		while (t.isAlive()) {
			// Wait maximum of 1 second for function thread to finish.
			try {
				t.join(1000);
			} catch (InterruptedException e) {
				console.getErr().println(e);
			}
			if (((System.currentTimeMillis() - startTime) > expiryTime * 1000) && t.isAlive()) {
				print(Thread.currentThread().getName() + " expired!");
				t.interrupt();
				// wait indefinitely for the thread to get interrupted
				try {
					t.join();
				} catch (InterruptedException e) {
					console.getErr().println(e);
				}
				return false;
			}

		}
		return true;
	}

	@Override
	public void onTick(Instrument instrument, ITick tick) throws JFException {
	}

	@Override
	public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
	}

	@Override
	public void onMessage(IMessage message) throws JFException {
	}

	@Override
	public void onAccount(IAccount account) throws JFException {
	}

	@Override
	public void onStop() throws JFException {
	}

	private void print(Object o) {
		console.getOut().println(o);
	}

}
