package jfx;


import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.awt.Color;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;


import com.dukascopy.api.*;
import com.dukascopy.api.drawings.IOhlcChartObject;
import com.dukascopy.api.IIndicators.AppliedPrice;
import com.dukascopy.api.IIndicators.MaType;

public class BASE implements IStrategy {
    private IEngine engine;
    private IConsole console;
    private IHistory history;
    private IContext context;
    private IIndicators indicators;


    @Configurable("Instrument")
    public Instrument instrument = Instrument.EURUSD;
    @Configurable("Period")
    public Period period = Period.ONE_MIN;
    //@Configurable("Filter")
    //public Filter filter = Filter.NO_FILTER;
    @Configurable("side")
    public OfferSide side = OfferSide.BID;
    //@Configurable("emaTimePeriod")
    //public int emaTimePeriod = 12;
    @Configurable("macdSignalPeriod")
    public int macdSignalPeriod = 9;
    @Configurable("macdSlowPeriod")
    public int macdSlowPeriod = 26;
    @Configurable("macdFastPeriod")
    public int macdFastPeriod = 12;
    @Configurable("acFastPeriod")
    public int acFastPeriod = 5;
    @Configurable("acSlowPeriod")
    public int acSlowPeriod = 34;
    @Configurable("FasterMATimePeriod")
	public int FasterMATimePeriod = 5;
	@Configurable("FasterMaType")
	public MaType FasterMaType = MaType.SMA;
	@Configurable("SlowerMATimePeriod")
	public int SlowerMATimePeriod = 10;
	@Configurable("SlowerMAType")
	public MaType SlowerMAType = MaType.SMA;

    DecimalFormat df = new DecimalFormat("0.0000000##");
    @SuppressWarnings("serial")
    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") {
        {
            setTimeZone(TimeZone.getTimeZone("GMT"));
        }
    };

       

    public void onStart(IContext context) throws JFException {
        this.engine = context.getEngine();
        this.console = context.getConsole();
        this.history = context.getHistory();
        this.context = context;
        this.indicators = context.getIndicators();
      
        //add indicators to chart and setup OHLC informer to show indicator values
        if(!addToChart(context.getChart(instrument))){
            printErr("Indicators did not get plotted on chart, because of chart feed mismatch.");
        }  
    }

    private boolean addToChart(IChart chart){
        if(chart == null){
            printErr("chart for "+ instrument+" not opened!");    
            return false;
        } 
        if (chart.getSelectedOfferSide() != this.side) {
            printErr("chart offer side is not " + this.side);
            return false;
        }  
        if (chart.getSelectedPeriod() != this.period) {
            printErr("chart period is not " + this.period);
            return false;
        } 
        /*if(chart.getFilter() != this.filter){
            printErr("chart filter is not " + this.filter);
            return false;
        }*/
        
        //chart.addIndicator(indicators.getIndicator("EMA"), new Object[] { emaTimePeriod });
        chart.addIndicator(indicators.getIndicator("MACD"), new Object[] { macdFastPeriod, macdSlowPeriod, macdSignalPeriod });
        chart.addIndicator(indicators.getIndicator("AC"), new Object[] {acFastPeriod, acSlowPeriod});
        chart.addIndicator(indicators.getIndicator("awesome"), new Object[] {FasterMATimePeriod, FasterMaType, SlowerMATimePeriod, SlowerMAType });

        IOhlcChartObject ohlc = null;
        for (IChartObject obj : chart.getAll()) {
            if (obj instanceof IOhlcChartObject) {
                ohlc = (IOhlcChartObject) obj;
            }
        }
        if (ohlc == null) {
            ohlc = chart.getChartObjectFactory().createOhlcInformer();
            chart.addToMainChart(ohlc);
        }
        ohlc.setShowIndicatorInfo(true);
        return true;
    }

    
    public void onAccount(IAccount account) throws JFException {
    }

    public void onMessage(IMessage message) throws JFException {
    }

    public void onStop() throws JFException {
        print("Stopped!");
    }

    public void onTick(Instrument instrument, ITick tick) throws JFException {
    }

    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {

        if (instrument.equals(instrument) && period.equals(period)) {

    		double[] macd = indicators.macd(instrument, period, side, AppliedPrice.CLOSE, macdFastPeriod, macdSlowPeriod, macdSignalPeriod, 1);
            //double ema = indicators.ema(instrument, period, side, AppliedPrice.CLOSE, emaTimePeriod, 1);
            double[] ac =  indicators.ac(instrument, period, side, AppliedPrice.CLOSE, acFastPeriod, acSlowPeriod, 1);
            double[] awesome =  indicators.awesome(instrument, period, side, AppliedPrice.CLOSE, FasterMATimePeriod, FasterMaType, SlowerMATimePeriod, SlowerMAType, 1);
            
            print("%s - macd=%s, ac=%s, awesome=%s", sdf.format(bidBar.getTime()), arrayToString(macd),arrayToString(ac),arrayToString(awesome));
        
            
        }
    }

    public void print(Object o) {
        this.console.getOut().println(o.toString());
    }

    private void print(long time, Object o) {
        print(sdf.format(time) + " " + o);
    }
    
    private void print(String format, Object...args){
        print(String.format(format,args));
    }
    
    private void printErr(Object o){
        console.getErr().println(o);
   }

    private static String arrayToString(double[] arr) {
        StringBuilder str = new StringBuilder();
        for (int r = 0; r < arr.length; r++) {
            str.append(String.format("[%s] %.5f; ", r, arr[r]));
        }
        return str.toString();
    }
}
