import java.util.HashSet;
import com.dukascopy.api.Configurable;
import com.dukascopy.api.IAccount;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IConsole;
import com.dukascopy.api.IContext;
import com.dukascopy.api.IEngine;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.IIndicators;
import com.dukascopy.api.IIndicators.AppliedPrice;
import com.dukascopy.api.IMessage;
import com.dukascopy.api.IMessage.Type;
import com.dukascopy.api.IOrder;
import com.dukascopy.api.IStrategy;
import com.dukascopy.api.ITick;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.JFException;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.Period;

public class FooStrategy implements IStrategy {

	@Configurable(value = "Instrument")
	public Instrument instrument = Instrument.EURSEK;

	@Configurable(value = "Period")
	public Period period = Period.ONE_HOUR;

	@Configurable(value = "Time period", stepSize = 12)
	public int timePeriod = 4;

	private IEngine engine;
	private IIndicators indicators;
	private IConsole console;

	private HashSet<Instrument> subscribedInstruments;

	private long orderId;

	@Override
	public void onStart(IContext context) throws JFException {

		engine = context.getEngine();
		indicators = context.getIndicators();
		console = context.getConsole();

		subscribedInstruments = new HashSet<Instrument>();
		subscribedInstruments.add(instrument);
		context.setSubscribedInstruments(subscribedInstruments);
	}

	@Override
	public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {

		if (!isOnBarInputValid(instrument, period, askBar, bidBar)) {
			return;
		}

		double[] keltner = indicators.keltner(instrument, Period.ONE_HOUR, OfferSide.ASK, AppliedPrice.CLOSE,
				timePeriod, 1);

		String label;
		OrderCommand orderCommand = null;
		double amountInMillions = 0.001;
		double price = 0;
		double slippageValue = Double.NaN;
		double stopLossPrice = 0;
		double takeProfitPrice = 0;
		long goodTillTime = 0;
		String comment = "";

		if (askBar.getClose() < keltner[2]) {

			// Submit long order
			label = "Buy_" + orderId++;
			orderCommand = OrderCommand.PLACE_BID;
			price = askBar.getLow();
			comment = "" + price;

			engine.submitOrder(label, instrument, orderCommand, amountInMillions, price, slippageValue, stopLossPrice,
					takeProfitPrice, goodTillTime, comment);
		}
	}

	@Override
	public void onTick(Instrument instrument, ITick tick) throws JFException {
		// ignore
	}

	@Override
	public void onMessage(IMessage message) throws JFException {
		if (message.getType() == Type.ORDER_FILL_OK) {
			IOrder order = message.getOrder();
			console.getOut()
					.println("Order filled @ " + order.getOpenPrice() + ", bid was placed @ " + order.getComment());
		}
	}

	@Override
	public void onAccount(IAccount account) throws JFException {
		// ignore
	}

	@Override
	public void onStop() throws JFException {
		// ignore
	}

	private boolean isOnBarInputValid(Instrument instrument, Period period, IBar askBar, IBar bidBar) {

		if (instrument == null) {
			return false;
		}

		if (period == null) {
			return false;
		}

		if (askBar == null) {
			return false;
		}

		if (bidBar == null) {
			return false;
		}

		if (!subscribedInstruments.contains(instrument)) {
			return false;
		}

		if (period != this.period) {
			// OK, but we do not want to process it
			return false;
		}

		if (askBar.getVolume() <= 0) {
			return false;
		}

		if (bidBar.getVolume() <= 0) {
			return false;
		}

		return true;
	}
}
