package jforex.bugtests.customInd;
 
 
import com.dukascopy.api.indicators.*;
 
import com.dukascopy.api.IConsole;
 
import java.awt.*;
import java.util.*;
 
 
public class Myind2 implements IIndicator , IDrawingIndicator {
 
     
    public static final Color UP      = new Color(0xc0, 0x00, 0x00);
    public static final Color DOWN    = new Color(0x00, 0x80, 0x00);
    public static final Color NEUTRAL = new Color(0x00, 0x00, 0x00);
     
     
    private IndicatorInfo           TrendIndicatorInfo;
    private InputParameterInfo[]    TrendInputParameterInfos;
    private OptInputParameterInfo[] TrendOptInputParameterInfos;
    private OutputParameterInfo[]   TrendoutputParameterInfos;
 
    private boolean OverChart       = true;
    private boolean OverVolumes     = false;    
    private boolean UnstablePeriod  = false;
     
    private int     NumberOfInputs  = 1;
    private int     NumberOptInputs = 2;
    private int     NumberOfOutputs = 2;
 
    private IConsole Console;
 
    private     IIndicator TM1InATR;
    private int TM1PeriodeATR   = 5;
 
    private     IIndicator TM1InCCI;
    private int TM1PeriodeCCI   = 38;
 
    private double[][][] PTM1Inputs  = new double[1][][];
    private Object[][]   OUTGraphics1  = new Object[1][];
    
    //Support: added new output array
    private double[][] doubleOutputs = new double[1][];
     
    private double TTM1Actual = 0;
    private double TTM1Before = 0;
    private int    TTM1Status = 0;
 
    private static class clData  {
        private  double TPoint = 0;
        private  int    TColor = 0;        
    }
     
    public void Print (String message) {
        this.Console.getOut( ).println(message);
    }
 
    public void onStart(IIndicatorContext context) {
 
 
        Console   = context.getConsole();
 
        TM1InATR = context.getIndicatorsProvider().getIndicator("ATR");
        TM1InCCI = context.getIndicatorsProvider().getIndicator("CCI");
 
        TM1InATR.setOptInputParameter(0, TM1PeriodeATR);
        TM1InCCI.setOptInputParameter(0, TM1PeriodeCCI);
 
 
        TrendIndicatorInfo = new IndicatorInfo("Trend2", "Master Trend", "Forex",
              OverChart, OverVolumes, UnstablePeriod, NumberOfInputs, NumberOptInputs, NumberOfOutputs);
 
        TrendInputParameterInfos = new InputParameterInfo[] {                                       
                                        new InputParameterInfo("TM1 Flux PRICE",  InputParameterInfo.Type.PRICE),
                                    };
        
        TrendOptInputParameterInfos = new OptInputParameterInfo[] {
                                        new OptInputParameterInfo("ATR", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(TM1PeriodeATR,  2,  20,  1)),
                                        new OptInputParameterInfo("CCI", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(TM1PeriodeCCI, 10, 100, 10))
                                     };
         
        TrendoutputParameterInfos = new OutputParameterInfo[] {            
            new OutputParameterInfo("OUTGraphics1", OutputParameterInfo.Type.OBJECT, OutputParameterInfo.DrawingStyle.LINE)
            {{
                setDrawnByIndicator(true);
            }},
            //Support:
            //don't draw - just for retrieval from strategy
            new OutputParameterInfo("OUT", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE){{
            	setShowOutput(false);
            }}
        };
    }
 
    public IndicatorResult calculate(int startIndex, int endIndex)
    {
        if (startIndex - getLookback() < 0) {
            startIndex -= startIndex - getLookback();
        }
 
        if (startIndex > endIndex) {
            return new IndicatorResult(0, 0);
        }
 
        double[] PTM1BufferATR = new double [endIndex + 1 - getLookback()];
        double[] PTM1BufferCCI = new double [endIndex + 1 - getLookback()];
 
        TM1InATR.setOutputParameter(0, PTM1BufferATR);
        TM1InCCI.setOutputParameter(0, PTM1BufferCCI);
 
        TM1InATR.setInputParameter(0, PTM1Inputs[0]);
        TM1InCCI.setInputParameter(0, PTM1Inputs[0]);
 
        IndicatorResult TM1ResultATR = TM1InATR.calculate(startIndex, endIndex);
        IndicatorResult TM1ResultCCI = TM1InCCI.calculate(startIndex, endIndex);
 
        int NumberOfElements = Math.min (TM1ResultATR.getNumberOfElements(), TM1ResultCCI.getNumberOfElements());
 
        int i, k;
 
 
        for (i = 0, k = NumberOfElements; i < k; i++) {
         
 
            if (PTM1BufferCCI[i] >= 0 ){
                TTM1Actual = PTM1Inputs[0][0][i+getLookback()] - PTM1BufferATR[i];                 
                if (TTM1Actual < TTM1Before) {
                    TTM1Actual = TTM1Before;                            
                } else TTM1Status = 0;
            } 
             
            if (PTM1BufferCCI[i] <  0 ){                
                TTM1Actual = PTM1Inputs[0][1][i+getLookback()] + PTM1BufferATR[i];                
                 if (TTM1Actual > TTM1Before) {
                     TTM1Actual = TTM1Before;                                     
                } else TTM1Status = 1;                
            } 
 
            clData[] vaData    = new clData[1];
            vaData[0]          = new clData();
            vaData[0].TPoint   = TTM1Actual;  
            vaData[0].TColor   = TTM1Status;  
            OUTGraphics1[0][i] = vaData;
            
            //Support: assign values in double output array
            doubleOutputs[0][i] = TTM1Actual;
         
            TTM1Before  = TTM1Actual;
 
        }
        
 
        return new IndicatorResult(startIndex, i);
         
    }
 
        public IndicatorInfo getIndicatorInfo()
    {
        return TrendIndicatorInfo;
    }
 
    public InputParameterInfo getInputParameterInfo(int index)
    {
        if (index <= TrendInputParameterInfos.length) {
            return TrendInputParameterInfos[index];
        }
        return null;
    }
 
     
    public int getLookback()
    {
        return Math.max(TM1InATR.getLookback(),  TM1InCCI.getLookback());
    }
 
     
    public int getLookforward()
    {
        return 0;
    }
 
     
    public OptInputParameterInfo getOptInputParameterInfo(int index)
    {
        if (index <= TrendOptInputParameterInfos.length) {
            return TrendOptInputParameterInfos[index];
        }
        return null;
    }
 
     
    public OutputParameterInfo getOutputParameterInfo(int index)
    {
        if (index <= TrendoutputParameterInfos.length) {
            return TrendoutputParameterInfos[index];
        }
        return null;
    }
 
     
    public void setInputParameter(int index, Object array)
    {
        switch (index) {
            case 0 : {
                PTM1Inputs[0] = (double[][]) array ;
                break;
            }
            case 1 : { 
             
                break;
            }
        }    
    }
 
     
    public void setOptInputParameter(int index, Object value)
    {
         switch (index){
            case 0: {  
                TM1PeriodeATR = (Integer) value;
                TM1InATR.setOptInputParameter(0, TM1PeriodeATR);
 
                break;
            }
 
            case 1: {  
                TM1PeriodeCCI =  (Integer) value;
                TM1InCCI.setOptInputParameter(0, TM1PeriodeCCI);
                break;
            }
        }
    }
 
     
 
    public void setOutputParameter(int index, Object array)
    {
        switch (index){
            case 0: {
                OUTGraphics1[0] = (Object[]) array;
                break;
            }
            case 1: {  
                //Support: added 
            	doubleOutputs[0] = (double[]) array;
                break;
            }
        }
         
    }
 
    
 
      public Point drawOutput(Graphics g, int outputIdx, Object values2, Color color, Stroke stroke,
                           IIndicatorDrawingSupport indicatorDrawingSupport, java.util.List<Shape> shapes,
                           Map<Color, java.util.List<Point>> handles)
      {
           
          Object[] values = (Object[]) values2;
 
          if (values2 != null) {
               
              for (int j = indicatorDrawingSupport.getIndexOfFirstCandleOnScreen(), k =
                        j + indicatorDrawingSupport.getNumberOfCandlesOnScreen() ; j < k; j++) {
                
                  if ((values[j] != null) &&  ( j > 0)) {         
                                           
                      try {                             
                          clData[] Actual   = (clData[]) values[j];
                          clData[] Preced   = (clData[]) values[j-1];
                           
                          int[] xPoints = new int[2];
                          int[] yPoints = new int[2];    
                           
                          xPoints[0] = (int) indicatorDrawingSupport.getMiddleOfCandle(j - 1);
                          xPoints[1] = (int) indicatorDrawingSupport.getMiddleOfCandle(j);
                          
                          yPoints[0] = (int) indicatorDrawingSupport.getYForValue(Preced[0].TPoint);
                          yPoints[1] = (int) indicatorDrawingSupport.getYForValue(Actual[0].TPoint);
                              
                          switch (Actual[0].TColor){
                              case 0: {
                                  g.setColor (DOWN);
                                  break;
                              }
                              case 1: {  
                                  g.setColor (UP);
                                  break;
                              }
                              case 2: {  
                                  g.setColor (NEUTRAL);
                                  break;
                              }
                              default : {                                  
                                  g.setColor (Color.YELLOW);
                                  break;
                              }
                          }
                           
                          g.drawLine(xPoints[0] , yPoints[0] , xPoints[1], yPoints[1]) ;
                          g.drawLine(xPoints[0] , yPoints[0]-1 , xPoints[1], yPoints[1]-1) ;
                         
                                        
                      } 
                      catch (Exception e) {
                          Print ("Error : "+e.toString());
                      } 
                  }          
              } 
           } 
           return null;
       }  
   }