package jforex.strategies;

import java.io.File;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import com.dukascopy.api.*;

@RequiresFullAccess
public class CycleFromStrat implements IStrategy {
	private IConsole console;
	private IIndicators indicators;

	@Configurable("")
	public File indicatorJfxFile = new File("C:/temp/CycleIdentifier2.jfx");
	@Configurable("Instrument")
	public Instrument instrument = Instrument.EURUSD;
	@Configurable("Period")
	public Period period = Period.TEN_MINS;

	@Configurable("")
	public int PriceActionFilter = 1;
	@Configurable("")
	public int Length = 3;
	@Configurable("")
	public int MajorCycleStrength = 4;
	@Configurable("")
	public boolean UseCycleFilter = false;
	@Configurable("")
	public int UseFilterSMAorRSI = 1;
	@Configurable("")
	public int FilterStrengthSMA = 12;
	@Configurable("")
	public int FilterStrengthRSI = 21;
	@Configurable("")
	public int ConnectorLookback = 0;
	@Configurable("")
	public int ConnectorShift = 0;
	@Configurable("")
	public boolean ConnectorUnstablePeriod = false;
	
	double[] LineBuffer;
	double[] MajorCycleBuy;
	double[] MajorCycleSell;
	double[] MinorCycleBuy;
	double[] MinorCycleSell;
	double[] ZL1;

	DecimalFormat df = new DecimalFormat("0.00000");
	@SuppressWarnings("serial")
	SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss") {
		{
			setTimeZone(TimeZone.getTimeZone("GMT"));
		}
	};

	public void onStart(IContext context) throws JFException {
		this.console = context.getConsole();
		this.indicators = context.getIndicators();
		
		this.indicators.registerCustomIndicator(indicatorJfxFile);

	}

	private void print(Object o) {
		console.getOut().println(o);
	}

	public void onAccount(IAccount account) throws JFException {	}
	public void onMessage(IMessage message) throws JFException {	}
	public void onStop() throws JFException {	}
	public void onTick(Instrument instrument, ITick tick) throws JFException {	}

	public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
	
		if (instrument != this.instrument || period != this.period)
			return;

		Object[] optionalInputArray = new Object[] { PriceActionFilter, Length, MajorCycleStrength, UseCycleFilter, UseFilterSMAorRSI,
				FilterStrengthSMA, FilterStrengthRSI, ConnectorLookback, ConnectorShift, ConnectorUnstablePeriod };

		Object[] resultArr = indicators.calculateIndicator(this.instrument, this.period, new OfferSide[] { OfferSide.BID },
				"CycleIdentifier2", new IIndicators.AppliedPrice[] { IIndicators.AppliedPrice.CLOSE }, optionalInputArray,
				Filter.NO_FILTER, 4000, bidBar.getTime(), 0);

		int outCount = 6;
		//this array holds all outputs
		double[][] outputs = new double[outCount][];

		
		for (int i = 0; i < outCount; i++) {
			outputs[i] = (double[]) resultArr[i];
			switch (i) {
			case 0:
				LineBuffer = outputs[i];
				break;
			case 1:
				MajorCycleBuy = outputs[i];
				break;
			case 2:
				MajorCycleSell = outputs[i];
				break;
			case 3:
				MinorCycleBuy = outputs[i];
				break;
			case 4:
				MinorCycleSell = outputs[i];
				break;
			case 5:
				ZL1 = outputs[i];
				break;
			}
			//print(i + " " + arrayToStringLast(outputs[i], 3900, ","));
		}

		print(sdf.format(bidBar.getTime()) + " Outputs for the last 100 bars:");
		print("LineBuffer: " + lastNotZeroInfo(LineBuffer) + arrayToStringLast(LineBuffer, 3900, ","));
		print("MajorCycleBuy: " + lastNotZeroInfo(MajorCycleBuy) + arrayToStringLast(MajorCycleBuy, 3900, ","));
		print("MajorCycleSell: " + lastNotZeroInfo(MajorCycleSell) + arrayToStringLast(MajorCycleSell, 3900, ","));
		print("MinorCycleBuy: " + lastNotZeroInfo(MinorCycleBuy) + arrayToStringLast(MinorCycleBuy, 3900, ","));
		print("MinorCycleSell: " + lastNotZeroInfo(MinorCycleSell) + arrayToStringLast(MinorCycleSell, 3900, ","));
		print("ZL1: " + lastNotZeroInfo(ZL1) + arrayToStringLast(ZL1, 3900, ","));

	} 

	public String lastNotZeroInfo(double[] arr){
		for(int i=arr.length -1; i>0; i--){
			if (arr[i] != 0){
				return "last non-zero value " + arr[i] + " index: " + i + " ";
			}
		}
		return "all values are 0 ";
	}

	public String arrayToStringLast(double[] arr, int minIndex, String delim1) {
		String str = "";
		minIndex = minIndex < 0 ? 0 : minIndex;
		for (int r = minIndex; r < arr.length; r++) {
			str += " [" + r + "]" + df.format(arr[r]) + delim1;
		}
		return str;
	}
}
