package jforex;

import java.util.*; //Map
import java.awt.*; //Point
import java.awt.geom.*;

import com.dukascopy.api.*;
import com.dukascopy.api.IConsole;
import com.dukascopy.api.indicators.*;

public class Copy implements IIndicator, IDrawingIndicator {
    private IndicatorInfo indicatorInfo;
    private InputParameterInfo[] inputParameterInfos;
    private OptInputParameterInfo[] optInputParameterInfos;
    private OutputParameterInfo[] outputParameterInfos;
    private double[][][] inputs = new double[1][][];
    private IBar[][] barInputs = new IBar[1][];
    private int timePeriod = 2;
    private double[][] outputs = new double[5][];

    private IConsole console;
    private IIndicatorContext context;
        
    public void onStart(IIndicatorContext context) {
        this.console = context.getConsole();    // allows printing to console
        this.context = context;
        
        indicatorInfo = new IndicatorInfo("COPY", "Copies inputs(OCHLV) into outputs", "My indicators", true, false, true, 1, 1, 5);
        
        inputParameterInfos = new InputParameterInfo[] {new InputParameterInfo("Input data", InputParameterInfo.Type.PRICE)};
        
        optInputParameterInfos = new OptInputParameterInfo[] { new OptInputParameterInfo("Time period", OptInputParameterInfo.Type.OTHER,new IntegerRangeDescription(0, 0, 100, 1))};
        
	    outputParameterInfos = new OutputParameterInfo[] {
	        new OutputParameterInfo("Open", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE),
	        new OutputParameterInfo("Close", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE),
	        new OutputParameterInfo("High", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE),
	        new OutputParameterInfo("Low", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE),
	        new OutputParameterInfo("Volume", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.NONE)
	        };
            
        for(int i=0; i<outputParameterInfos.length; i++) { 
            outputParameterInfos[i].setDrawnByIndicator(false); // set to "true" to draw this indicator via drawOutput() method below (useless, ignore)
            }
        console.getOut().println("--- Copy indicator started");    
        }

    public IndicatorResult calculate(int startIndex, int endIndex) {
        //calculating startIndex taking into account lookback value
        if (startIndex - getLookback() < 0) {
            startIndex -= startIndex - getLookback();
            }
        
        /*
        ** Copy input data to output
        */
        int i, j;
        for (i = startIndex, j=0; i <= endIndex; i++, j++) {

        	for (int k = 0; k < 5; k++) {
        		outputs[k][j]=inputs[0][k][i];
        	    }
            }
        return new IndicatorResult(startIndex, j);
        }

    public Point drawOutput(Graphics g, int outputIdx, Object valuesArr, Color color, Stroke stroke, IIndicatorDrawingSupport indicatorDrawingSupport, java.util.List<Shape> shapes, Map<Color, java.util.List<Point>> handles) {
        console.getOut().println("--- drawOutput called");  
        
        IBar[] candles = indicatorDrawingSupport.getCandles();
        double[] values = (double[]) valuesArr;
        if (candles.length != values.length) {
            console.getErr().println(candles.length + " <> " + values.length);
            }

        GeneralPath path = new GeneralPath();
        boolean plottingStarted = false;

        for (int i = indicatorDrawingSupport.getIndexOfFirstCandleOnScreen() - 1, 
                 j = indicatorDrawingSupport.getIndexOfFirstCandleOnScreen() + indicatorDrawingSupport.getNumberOfCandlesOnScreen() + 1; 
                 i < j; 
                 i++)
                 {
                     
            if (i < 0 || i >= candles.length) {
                continue;
                }
                
            if (Double.isNaN(values[i])) {
                continue;
                }
                
            //double allignedValue = ((values[i] - gbpMin) / (gbpMax - gbpMin)) * (max - min) + min;
            float x = indicatorDrawingSupport.getMiddleOfCandle(i);
            float y = indicatorDrawingSupport.getYForValue(values[i]);
            if (plottingStarted) {
                path.lineTo(x, y);
            } else {
                path.moveTo(x, y);
                plottingStarted = true;
                }
            }
        g.setColor(color);
        //((Graphics2D) g).setStroke(stroke);
        ((Graphics2D) g).draw(path);
        return null;
        }
    public IndicatorInfo getIndicatorInfo() {
        return indicatorInfo;
    }

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

    public int getLookback() {
        return timePeriod;
    }

    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) {

        if(inputParameterInfos[0].getType() == InputParameterInfo.Type.PRICE) {
            inputs[index] = (double[][]) array;
            return;
            }
        
        /*
        ** Acquire Bar type input
        */    
        IBar bar;
        barInputs[index] = (IBar[]) array;
        int len = barInputs[index].length;
        inputs[index] = new double[5][len];
        
        for (int j = 0; j < len; j++) {
            bar = barInputs[index][j];
            inputs[index][0][j] = bar.getOpen();
            inputs[index][1][j] = bar.getClose();
            inputs[index][2][j] = bar.getHigh();
            inputs[index][3][j] = bar.getLow();
            inputs[index][4][j] = bar.getVolume();
            }
        }

    public void setOptInputParameter(int index, Object value) {
        timePeriod = (Integer) value;
    }

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