package jforex;

import java.awt.Color;

import com.dukascopy.api.indicators.IIndicator;
import com.dukascopy.api.indicators.IIndicatorContext;
import com.dukascopy.api.indicators.IndicatorInfo;
import com.dukascopy.api.indicators.IndicatorResult;
import com.dukascopy.api.indicators.InputParameterInfo;
import com.dukascopy.api.indicators.OptInputParameterInfo;
import com.dukascopy.api.indicators.OutputParameterInfo;

public class LeggingIndicator implements IIndicator {

	private IIndicator indMACD;

	final private double[][][] inputs = new double[1][][];
	
	final private double[][] outputs = new double[1][];

	/**
	 * This Indicator Info
	 */
	private IndicatorInfo indicatorInfo;

	/**
	 * Input data info
	 */
	private InputParameterInfo[] inputParameterInfos;

	/**
	 * Output (ie. DOT) paramter info like color
	 */
	private OutputParameterInfo[] outputParameterInfos;

	/**
	 * Optional Input (time priod, X, etc) parameter info
	 */
	private OptInputParameterInfo[] optInputParameterInfos;

	public void onStart(IIndicatorContext context) {
		indMACD = context.getIndicatorsProvider().getIndicator("MACD");

		indicatorInfo = new IndicatorInfo(getName(), getName(), getName(), false, false, true, 1, 0, 1);

		// This is data to be passed in Calculate method
		inputParameterInfos = new InputParameterInfo[] { new InputParameterInfo("Input data", InputParameterInfo.Type.PRICE) };

		// Setting Indicator input paramter
		optInputParameterInfos = new OptInputParameterInfo[] {};

		// Number of dots
		outputParameterInfos = new OutputParameterInfo[] { opi1("Color", Color.BLUE) };
	}

	final private OutputParameterInfo opi1(String title, Color c) {
		OutputParameterInfo opi = new OutputParameterInfo(title, OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE);
		opi.setDrawnByIndicator(false);
		return opi;
	}
	
	/**
	 * Calculate Output parameter, Means x,y value for dot
	 * 
	 * Start and End Index is given by JForex. We have calculate dot value for
	 * each index between start and end index (Bar)
	 */
	public IndicatorResult calculate(int startIndex, int endIndex) {
		if (startIndex - getLookback() < 0) {
			startIndex -= startIndex - getLookback();
		}
		if (startIndex > endIndex) { return new IndicatorResult(0, 0); }

		double[][] macdOut = calculateMacd(indMACD, inputs[0][1], 12, 26, 9, startIndex, endIndex);

		int i, j;
		for (i = startIndex, j = 0; i <= endIndex; i++, j++) {
			// Inputs: 0 open, 1 close, 2 high, 3 low, 4 volume

			double macd = macdOut[0][j];
			outputs[0][j] = macd;
		}
		return new IndicatorResult(startIndex, j);
	}

	public double[][] calculateMacd(IIndicator indi, Object inputs, int fastPeriod, int slowPeriod, int signalPeriod, int startIndex, int endIndex) {
		indi.setOptInputParameter(0, fastPeriod);
		indi.setOptInputParameter(1, slowPeriod);
		indi.setOptInputParameter(2, signalPeriod);

		double[] macdA = new double[endIndex - startIndex + 2 + indi.getLookback()];
		double[] macdA2 = new double[endIndex - startIndex + 2 + indi.getLookback()];
		double[] macdA3 = new double[endIndex - startIndex + 2 + indi.getLookback()];

		indi.setInputParameter(0, inputs);
		indi.setOutputParameter(0, macdA);
		indi.setOutputParameter(1, macdA2);
		indi.setOutputParameter(2, macdA3);
		indi.calculate(startIndex, endIndex);
		return new double[][] { macdA, macdA2, macdA3 };
	}
	
	
	final public IndicatorInfo getIndicatorInfo() {
		return indicatorInfo;
	}

	/**
	 * used to passs values[like open, close, high, low] to calculate method
	 */
	final public InputParameterInfo getInputParameterInfo(int index) {
		if (index <= inputParameterInfos.length) { return inputParameterInfos[index]; }
		return null;
	}

	/**
	 * Used by Indicator selector dialog to create component to accept input
	 * parameter
	 */
	final public OptInputParameterInfo getOptInputParameterInfo(int index) {
		if (index <= optInputParameterInfos.length) { return optInputParameterInfos[index]; }
		return null;
	}

	/**
	 * Dot info
	 */
	final public OutputParameterInfo getOutputParameterInfo(int index) {
		if (index <= outputParameterInfos.length) { return outputParameterInfos[index]; }
		return null;
	}

	/**
	 * Set current values for Input (array of OHCL data)
	 */
	final public void setInputParameter(int index, Object array) {
		inputs[index] = (double[][]) array;
	}

	/**
	 * Set output parameter
	 */
	final public void setOutputParameter(int index, Object array) {
		outputs[index] = (double[]) array;
	}

	public String getName() {
		return "CF-ffff1";
	}

	/**
	 * Used while calculating and drawing dot. How much bars needed to calculate
	 * current value
	 */
	public int getLookback() {
		return 26;
	}

	@Override
	public int getLookforward() {
		return 0;
	}

	/**
	 * Set Input parameter
	 */
	public void setOptInputParameter(int index, Object value) {
	}
}