package jforex;
 
import com.dukascopy.api.IIndicators;
import com.dukascopy.api.indicators.*;
import java.lang.String;
import java.text.SimpleDateFormat;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IConsole;
import java.text.DateFormat;
import java.text.ParseException;
 
import java.text.SimpleDateFormat; 
import com.dukascopy.api.IBar;
import com.dukascopy.api.IConsole;
import java.text.DateFormat;
import java.text.ParseException;
 
import java.util.*;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Shape;
import java.awt.Stroke;
import java.util.Map;
 
/**
 * Created by: chriz aka Indiana Pips
 * Date: Feb 07, 2011
 * email: puntasabbioni/AT/gmail.com 
 */
  
public class MultiMARibbon2 implements IIndicator , IDrawingIndicator {
 
    public static final int FASTMA = 0;
    public static final int SLOWMA = 1;
     
    private IBar[] inputBars;
    private IIndicator fastMaIndi;
    private IIndicator slowMaIndi;
     
    private int fastTimePeriod = 5;
    private int slowTimePeriod = 34;
     
    public  String  startdate = "2018-02-01 00:00:00";
    public  String  enddate   = "2018-02-12 00:00:00";
    public static final Color GREEN = new Color(0x00, 0x80, 0x00);
    public static final Color RED = new Color(0xc0, 0x00, 0x00);
    public static final Color LIGHT_GREEN = new Color(0x80, 0xFF, 0x80);
    public static final Color LIGHT_RED  = new Color(0xFF, 0x80, 0x80);
    public static final Color VERY_DARK_YELLOW = new Color(0x80, 0x80, 0x00);
    public static final Color DARK_RED = new Color(0xc0, 0x00, 0x00);
    public static final Color VERY_DARK_RED = new Color(0x80, 0x00, 0x00);
    public static final Color VERY_DARK_GREEN = new Color(0x00, 0x80, 0x00);
    public static final Color DARK_GREEN = new Color(0x00, 0xC0, 0x00);
 
                 
    private IndicatorInfo indicatorInfo;
    private InputParameterInfo[] inputParameterInfos;
    private OptInputParameterInfo[] optInputParameterInfos;
    private OutputParameterInfo[] outputParameterInfos;
    private double[][] inputs = new double[2][];
    private double[][] outputs = new double[4][];
    private Object[][] output = new Object[1][];
    private IIndicatorContext context ;
 
    private InputParameterInfo inputParam1 ;
    private InputParameterInfo inputParam2 ;
    private InputParameterInfo inputParam3 ;
 
    public void onStart(IIndicatorContext context) {
        this.context = context ;
         
        IIndicatorsProvider indicatorsProvider = context.getIndicatorsProvider();
        fastMaIndi = indicatorsProvider.getIndicator("MA");
        slowMaIndi = indicatorsProvider.getIndicator("MA");
         
        indicatorInfo = new IndicatorInfo("MARibbonFilled", "Ma Ribbon", "Overlap Studies", true, false, true, 3, 6, 5);
         
        inputParam1 = new InputParameterInfo("Fast MA Applied Price", InputParameterInfo.Type.DOUBLE);
        inputParam2 = new InputParameterInfo("Slow MA Applied Price", InputParameterInfo.Type.DOUBLE);
        inputParam3 = new InputParameterInfo("bars", InputParameterInfo.Type.BAR);
         
        inputParam1.setAppliedPrice(IIndicators.AppliedPrice.CLOSE);
        inputParam2.setAppliedPrice(IIndicators.AppliedPrice.CLOSE);
        
         
        inputParameterInfos = new InputParameterInfo[] { inputParam1, inputParam2, inputParam3 };
         
        int[] maValues = new int[IIndicators.MaType.values().length];
        String[] maNames = new String[IIndicators.MaType.values().length];
        for (int i = 0; i < maValues.length; i++) {
            maValues[i] = i;
            maNames[i] = IIndicators.MaType.values()[i].name();
        }
                                 
        optInputParameterInfos = new OptInputParameterInfo[] {
            new OptInputParameterInfo("startdate",     OptInputParameterInfo.Type.OTHER, new StringOptInputDescription("2018-02-01 00:00:00")),
            new OptInputParameterInfo("enddate",       OptInputParameterInfo.Type.OTHER, new StringOptInputDescription("2018-02-12 00:00:00")),
            new OptInputParameterInfo("FasterMA Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(5, 2, 2000, 1)),
            new OptInputParameterInfo("FasterMA Type", OptInputParameterInfo.Type.OTHER, new IntegerListDescription(IIndicators.MaType.SMA.ordinal(), maValues, maNames)),
            new OptInputParameterInfo("SlowerMA Time Period", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(34, 2, 2000, 1)),
            new OptInputParameterInfo("SlowerMA Type", OptInputParameterInfo.Type.OTHER, new IntegerListDescription(IIndicators.MaType.SMA.ordinal(), maValues, maNames))
        };
         
        outputParameterInfos = new OutputParameterInfo[] {
            new OutputParameterInfo("Fast MA", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE) {{
                setColor(Color.BLUE);
            }},
            new OutputParameterInfo("Slow MA", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE) {{
                setColor(Color.GREEN);
            }},
            new OutputParameterInfo("UP ARROW", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.ARROW_SYMBOL_UP){{                
                setColor(VERY_DARK_GREEN);                
            }},                        
            new OutputParameterInfo("DOWN ARROW", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.ARROW_SYMBOL_DOWN){{                
                setColor(VERY_DARK_RED);                
            }},            
            new OutputParameterInfo("MA Ribbon", OutputParameterInfo.Type.OBJECT, OutputParameterInfo.DrawingStyle.LINE) {{
                setDrawnByIndicator(true);
            }}            
        };
    }
 public static boolean compare_dateStr(String startdate, String enddate) {
        
        boolean isFirstBig = false;
        DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd ");
        try {
            Date dt1 = df1.parse(startdate);
            Date dt2 = df1.parse(enddate);
            if (dt1.getTime() > dt2.getTime()) {
                System.out.println("dt1>dt2");
                isFirstBig = true;
            } else if (dt1.getTime() < dt2.getTime()) {
                System.out.println("dt1<dt2");
                isFirstBig = false;
            } else {
                isFirstBig = false;
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return isFirstBig;
    }
  
    public Date stringToDateParser(String date) {
       DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd ");
        Date newDate = null;
        try {
            newDate = sdf.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return newDate;
    }    
    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);
        }        
                 
        double[] fastMAOut = new double[endIndex - startIndex + 1 + getLookback()];
        double[] slowMAOut = new double[endIndex - startIndex + 1 + getLookback()];
 
        // calculation on selected applied price
        fastMaIndi.setInputParameter(0, inputs[0]);
        slowMaIndi.setInputParameter(0, inputs[1]);
 
        fastMaIndi.setOutputParameter(0, fastMAOut);
        slowMaIndi.setOutputParameter(0, slowMAOut);
 
        IndicatorResult fastMaIndiResult = fastMaIndi.calculate(startIndex , endIndex);
        IndicatorResult slowMaIndiResult = slowMaIndi.calculate(startIndex , endIndex);
 
        int i, k;
        Date startDate = stringToDateParser(startdate);
        Date endDate = stringToDateParser(enddate);
        for (i = 0, k = slowMaIndiResult.getNumberOfElements(); i < k; i++) {
            if ( inputBars[i].getTime() >= startDate.getTime() && inputBars[i].getTime() <= endDate.getTime()){
            //-----
            outputs[0][i] = fastMAOut[i] ;
            outputs[1][i] = slowMAOut[i] ;
            outputs[2][i] = Double.NaN ;
            outputs[3][i] = Double.NaN ;
            if(i>0 && fastMAOut[i]>slowMAOut[i] && fastMAOut[i-1]<slowMAOut[i-1])
            {
                // UP SIGNAL
                outputs[2][i] = slowMAOut[i];    
            }
            if(i>0 && fastMAOut[i]<slowMAOut[i] && fastMAOut[i-1]>slowMAOut[i-1])
            {
                // DN SIGNAL
                outputs[3][i] = slowMAOut[i];    
            }            
             
            double[] ribbon = new double[2];
            ribbon[FASTMA] = fastMAOut[i] ;
            ribbon[SLOWMA] = slowMAOut[i] ;
            // for drawing
            output[0][i] = ribbon;
        }
        }
        
        context.getConsole().getOut().println();
        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() {
                 
        int fastMaLookBack = fastMaIndi.getLookback();
        int slowMaLookBack = slowMaIndi.getLookback();        
        return Math.max( fastMaLookBack, slowMaLookBack) ;
    }
 
    public OutputParameterInfo getOutputParameterInfo(int index) {
        if (index <= outputParameterInfos.length) {
            return outputParameterInfos[index];
        }
        return null;
    }
 
    public void setInputParameter(int index, Object array) {
        if(index < 2) {
            inputs[index] = (double[]) array;
        } else {
            inputBars = (IBar[]) 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 2:
                fastTimePeriod = (Integer) value;
                fastMaIndi.setOptInputParameter(0, fastTimePeriod);
                break;
            case 3:
                int maFastType = (Integer) value;
                fastMaIndi.setOptInputParameter(1,IIndicators.MaType.values()[maFastType].ordinal()); 
                break;                               
            case 4:
                slowTimePeriod = (Integer) value;
                slowMaIndi.setOptInputParameter(0, slowTimePeriod);
                break;
            case 5:
                int maSlowType = (Integer) value;
                slowMaIndi.setOptInputParameter(1,IIndicators.MaType.values()[maSlowType].ordinal()); 
                break;                                                              
            default:
//                throw new ArrayIndexOutOfBoundsException(index);
        }
    }
 
    public void setOutputParameter(int index, Object array) {
        if(index<4)
        {
            outputs[index] = (double[]) array;
        }else
        {
            output[0] = (Object[]) array;
        }
    }
 
    public int getLookforward() {
        return 0;
    }
 
    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 (j > 0) {
                                                                                     
                    if (values[j] != null) {
                        double[] pointPrev = (double[]) values[j - 1];
                        double[] point = (double[]) values[j];
                                             
                        int barMiddle = (int) indicatorDrawingSupport.getMiddleOfCandle(j );
                        int barMiddlePrev = (int) indicatorDrawingSupport.getMiddleOfCandle(j - 1);
                         
                        if (point[FASTMA] > point[SLOWMA]) {
                            Color color2 = new Color(0, 200, 0, 78);
                            g.setColor(color2);
                        } else {
                            Color color2 = new Color(200, 0, 0, 78);
                            g.setColor(color2);
                        }
                        int[] xPoints = new int[4];
                        int[] yPoints = new int[4];
                        if (pointPrev != null && point != null) {
                            yPoints[0] = (int) indicatorDrawingSupport.getYForValue(pointPrev[FASTMA]);
                            yPoints[1] = (int) indicatorDrawingSupport.getYForValue(point[FASTMA]);
                            yPoints[2] = (int) indicatorDrawingSupport.getYForValue(point[SLOWMA]);
                            yPoints[3] = (int) indicatorDrawingSupport.getYForValue(pointPrev[SLOWMA]);
 
 
                            xPoints[0] = barMiddlePrev;
                            xPoints[1] = barMiddle;
                            xPoints[2] = barMiddle;
                            xPoints[3] = barMiddlePrev;
 
                            g.fillPolygon(xPoints, yPoints, 4);
                        }
                    }
                }
            }           
        }
         
        return null;
    }
     
    private void print(String sss)
    {
        context.getConsole().getOut().println(sss) ;
    }
         
}