package jforex.test;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

import com.dukascopy.api.*;

/**
 * The strategy demonstrates how one can handle himself custom periods,
 * if platform functionality is not available (e.g. for JForex API 2.6.33)
 *
 */

public class EmulateCustomPeriod implements IStrategy {

	@Configurable("Instrument")
	public Instrument instrument = Instrument.EURUSD;
	@Configurable("Period (in secs)")
	public int periodInSecs = 7;
	@Configurable("Offer Side")
	public OfferSide side = OfferSide.BID;
	
	IHistory history;
	IConsole console;
	
	CustomBar customBar;
	ITick prevTick;
	long periodInMillis;
	
	
	@Override
	public void onStart(IContext context) throws JFException {

		history = context.getHistory();
		console = context.getConsole();

		prevTick = history.getLastTick(instrument);
		periodInMillis = periodInSecs * 1000;
	}
	
	private void print(Object o){
		console.getOut().println(o);
	}

	@Override
	public void onTick(Instrument instrument, ITick tick) throws JFException {
		if(instrument != this.instrument){
			return;
		}

		//we have a new period - execute custom bar logic and create a new bar
		if(prevTick.getTime() / periodInMillis < tick.getTime() / periodInMillis ){
			if(customBar != null){
				onCustomBar(customBar);
			}
			long barTimeRounded = tick.getTime() - tick.getTime() % periodInMillis;
			customBar = new CustomBar(tick, side, barTimeRounded);
		//update current bar's data 
		} else if (customBar != null) {
			customBar.updateBar(tick, side);
		} else {
			//note - here the first bar has not been created yet, so we just need to wait for the time condition to fulfill
			//alternatively one can load some ticks from history in order to create the first bar
		}
		
		
		prevTick = tick;
	}
	
	private void onCustomBar(IBar bar){
		print ("TODO: action on custom bar: " + bar);
	}

	@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 {}
	
	public class CustomBar implements IBar {

		public double open;
		public double close;
		public double low;
		public double high;
		public double vol;
		public long time;
		
		@SuppressWarnings("serial")
		private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") {	{setTimeZone(TimeZone.getTimeZone("GMT"));	}};
		private DecimalFormat df = new DecimalFormat("0.00000");

		public CustomBar(ITick tick, OfferSide offerSide, long time) {
			double price = offerSide == OfferSide.BID ? tick.getBid() : tick.getAsk();
			double volume = offerSide == OfferSide.BID ? tick.getBidVolume() : tick.getAskVolume();
			
			open = close = low = high = price;
			vol = volume;
			this.time = time;
		}
		
		public CustomBar(double open, double close, double low, double high, double vol, long time) {
			this.open = open;
			this.close = close;
			this.low = low;
			this.high = high;
			this.vol = vol;
			this.time = time;		
		}
		
		public void updateBar(ITick tick, OfferSide offerSide) {
			double price = offerSide == OfferSide.BID ? tick.getBid() : tick.getAsk();
			double volume = offerSide == OfferSide.BID ? tick.getBidVolume() : tick.getAskVolume();
			
			close = price;
			if(price < low){
				low = price;
			}
			if(price > high){
				high = price;
			}
			//bar volumes are sum of their tick volumes
			vol += volume;
		}

		@Override
		public double getOpen() {
			return open;
		}

		@Override
		public double getClose() {
			return close;
		}

		@Override
		public double getLow() {
			return low;
		}

		@Override
		public double getHigh() {
			return high;
		}

		@Override
		public double getVolume() {
			return vol;
		}

		@Override
		public long getTime() {
			return time;
		}

		@Override
		public String toString() {
			StringBuilder str = new StringBuilder();
			str.append(time).append("[").append(sdf.format(time)).append("] O: ")
					.append(df.format(open)).append(" C: ").append(df.format(close)).append(" H: ").append(df.format(high)).append(" L: ")
					.append(df.format(low)).append(" V: ").append(df.format(vol));
			return str.toString();
		}

	}

}
