package jforex;

import com.dukascopy.api.indicators.*;

public class OsMAIndicator implements IIndicator {
    private IndicatorInfo indicatorInfo;
    private InputParameterInfo[] inputParameterInfos;
    private OptInputParameterInfo[] optInputParameterInfos;
    private OutputParameterInfo[] outputParameterInfos;
    private double[][] inputs = new double[1][];
    private int fastPeriod = 12;
    private int slowPeriod = 26;
    private int signalPeriod = 9;
    private double[][] outputs = new double[1][];
    private IIndicator ind01;
    
    public void onStart(IIndicatorContext context) {
        ind01 = context.getIndicatorsProvider().getIndicator("ULTOSC");
        indicatorInfo = new IndicatorInfo("CustULTOSC", "Moving Average of Oscillator", "Momentum Oscillators",
        		false, false, false, 1, 3, 1);
        inputParameterInfos = new InputParameterInfo[] {new InputParameterInfo("Input data", InputParameterInfo.Type.DOUBLE)};
        optInputParameterInfos = new OptInputParameterInfo[] {
            new OptInputParameterInfo("Fast period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(12, 2, 100, 1)),
            new OptInputParameterInfo("Slow period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(26, 2, 100, 1)),
            new OptInputParameterInfo("Slowest period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(9, 2, 100, 1))
        };
        outputParameterInfos = new OutputParameterInfo[] {new OutputParameterInfo("out", OutputParameterInfo.Type.DOUBLE,
                OutputParameterInfo.DrawingStyle.LINE)};
    }

    public IndicatorResult calculate(int startIndex, int endIndex) {
        //calculating startIndex taking into account lookback value
        if (startIndex - getLookback() < 0) {
            startIndex -= startIndex - getLookback();
        }
        
        if (startIndex > endIndex) {
            return new IndicatorResult(0, 0);
        }
        ind01.setOptInputParameter(0, fastPeriod);
        ind01.setOptInputParameter(1, slowPeriod);
        ind01.setOptInputParameter(2, signalPeriod);
                        
        double[] macdA = new double[endIndex + 1 - ind01.getLookback()];
        double[] macdA2 = new double[endIndex + 1 - ind01.getLookback()];
        ind01.setInputParameter(0, inputs[0]);
        ind01.setOutputParameter(0, macdA);
        ind01.setOutputParameter(1, macdA2);
        IndicatorResult dMACDResult = ind01.calculate(startIndex, endIndex);
                
        int i, k;
        for (i = 0, k = dMACDResult.getNumberOfElements(); i < k; i++) {
            outputs[0][i] =  macdA[i];
        }
        return new IndicatorResult(startIndex, i);
    }

    public IndicatorInfo getIndicatorInfo() {
        return indicatorInfo;
    }

    public InputParameterInfo getInputParameterInfo(int index) {
        if (index <= inputParameterInfos.length) {
            return inputParameterInfos[index];
        }
        return null;
    }

    public int getLookback() {
        return ind01.getLookback();
    }

    public int getLookforward() {
        return 0;
    }

    public OptInputParameterInfo getOptInputParameterInfo(int index) {
        if (index <= optInputParameterInfos.length) {
            return optInputParameterInfos[index];
        }
        return null;
    }

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

    public void setInputParameter(int index, Object array) {
        inputs[index] = (double[]) array;
    }

    public void setOptInputParameter(int index, Object value) {
        if (index == 0) {
            fastPeriod = (Integer) value;
        } else if (index == 1) {
            slowPeriod = (Integer) value;
        } else {
            signalPeriod = (Integer) value;
        }
    }

    public void setOutputParameter(int index, Object array) {
        outputs[index] = (double[]) array;
    }
}
