import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.GeneralPath;
import java.util.List;
import java.util.Map;

import com.dukascopy.api.IBar;
import com.dukascopy.api.ITick;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.indicators.IDrawingIndicator;
import com.dukascopy.api.indicators.IIndicator;
import com.dukascopy.api.indicators.IIndicatorContext;
import com.dukascopy.api.indicators.IIndicatorDrawingSupport;
import com.dukascopy.api.indicators.IMinMax;
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;
import com.dukascopy.api.indicators.DoubleRangeDescription;
import com.dukascopy.api.indicators.IntegerRangeDescription;

public class Test10 implements IIndicator
{
	private static final int OPEN = 0;
	private static final int CLOSE = 1;
	private static final int HIGH = 2;
	private static final int LOW = 3;
	private static final int VOLUME = 4;
    private double trail_distance = 0.0005;   
    	
    private IndicatorInfo indicatorInfo;
    private InputParameterInfo[] inputParameterInfos;
    private OutputParameterInfo[] outputParameterInfos;
    private OptInputParameterInfo[] optInputParameterInfos;
    
    private static final Color DIM_BLUE = new Color(51, 153, 255); 
    private static final Color DIM_RED = new Color(222, 57, 57);
    private static final Color MAGENTA = new Color(125, 0, 125);        
    
    private double[][][] inputs = new double[1][][];
    private double[][] outputs = new double[2][];
    private double reff_mid = 1.4260;    
    private static int flag = 0;              private static int flag1 = 0;
    private static double up_trail=50000;     private static double dn_trail=0;
        
    public void onStart(IIndicatorContext context) 
    {
       	indicatorInfo = new IndicatorInfo("Test10", "Test10", "Custom", true, false, true, 1, 1, 2);
       	inputParameterInfos = new InputParameterInfo[] {
                new InputParameterInfo("Price", InputParameterInfo.Type.PRICE)              
        };
        optInputParameterInfos = new OptInputParameterInfo[] {
            new OptInputParameterInfo("Reff Mid", OptInputParameterInfo.Type.OTHER, new DoubleRangeDescription(reff_mid, 0, 100, 0.0001, 6)),
            };        
        outputParameterInfos = new OutputParameterInfo[] {
                new OutputParameterInfo("Reff zig-zag", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE)
                {{
                	setColor(MAGENTA);
                	setShowValueOnChart(true);
                }},                          
                new OutputParameterInfo("True zig-zag", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE)
                {{
                	setColor(MAGENTA);
                	setShowValueOnChart(true);
                }},                
        };
    }

    public IndicatorResult calculate(int startIndex, int endIndex) 
    {
        int start = startIndex;
        if (startIndex - getLookback() < 0) {start -= startIndex - getLookback();}
        int outputLen = endIndex - start + 1;
        
        double reff = reff_mid;
        for(int i = 0; i < outputLen; i++)
        {
                up_trail=Math.min(up_trail,inputs[0][HIGH][i]+trail_distance);
                dn_trail=Math.max(dn_trail,inputs[0][LOW][i]-trail_distance);
                
                if (inputs[0][HIGH][i]>up_trail && flag!=1) {flag=1; dn_trail=inputs[0][LOW][i]-trail_distance;}
                else {if(inputs[0][LOW][i]<dn_trail && flag!=-1) {flag=-1; up_trail=inputs[0][HIGH][i]+trail_distance;}}
                
                if (flag==1) {outputs[1][i] = dn_trail;}
                else {if (flag==-1) {outputs[1][i] = up_trail;}}
                
                if (inputs[0][HIGH][i]>Math.max(reff,outputs[1][i])) {flag1=1;}
                else {if (inputs[0][LOW][i]<Math.min(reff,outputs[1][i])) {flag1=-1;}}
                if (flag1==1) {outputs[0][i] = Math.min(outputs[1][i], reff);}
                else {if (flag1==-1) {outputs[0][i] = Math.max(outputs[1][i], reff);}}
        }
        
        return new IndicatorResult(start, outputLen);
    }


    public IndicatorInfo getIndicatorInfo() {
        return indicatorInfo;
    }

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

    public int getLookback() {
        return 0;
    }

    public int getLookforward() {
        return 0;
    }
    
    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 OptInputParameterInfo getOptInputParameterInfo(int index) {
        if (index <= optInputParameterInfos.length) {
            return optInputParameterInfos[index];
        }
        return null;
    }

    public void setOptInputParameter(int index, Object value) {
    	 switch (index) {	        	
         case 0:
             reff_mid = (Double) value;   	  
             break;
         default:
             throw new ArrayIndexOutOfBoundsException(index);
    	 }
    }

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



