package jforex.strategies.indicators;


import com.dukascopy.api.*;
import com.dukascopy.api.IIndicators.AppliedPrice;
import com.dukascopy.api.drawings.IOhlcChartObject;
import com.dukascopy.api.indicators.IIndicator;

public class AddToChartT3 implements IStrategy {
    private IIndicators indicators;
    private IChart chart;
    private IConsole console;
    private IOhlcChartObject ohlc = null;
    
    @Configurable("")
    public Filter filter = Filter.NO_FILTER;
    @Configurable("")
    public Instrument instrument = Instrument.EURUSD;
    @Configurable("")
    public Period period = Period.TEN_SECS;
    @Configurable("")
    public OfferSide side = OfferSide.BID;
    @Configurable("")
    public AppliedPrice appliedPrice = AppliedPrice.CLOSE;
    @Configurable("")
    public int t3TimePeriod = 5;
    @Configurable("")
    public double t3VFactor = 0.7;
    @Configurable("")
    public boolean addToChart = true;
    

    public void onStart(IContext context) throws JFException {
        this.indicators = context.getIndicators();
        this.chart = context.getChart(Instrument.EURUSD);
        this.console = context.getConsole();
        
        if(addToChart){
            IIndicator indicator = indicators.getIndicator("T3");
            Object[] optInputs = new Object[]{t3TimePeriod, t3VFactor};
            chart = context.getChart(instrument);
            addToChart(chart, indicator, optInputs);
        }  
    }
    
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {  
        if(period != this.period || instrument != this.instrument){
            return;
        }
        
        double prevT3 = indicators.t3(instrument, period, side, appliedPrice, t3TimePeriod, t3VFactor, 1);
        IBar bar = side == OfferSide.BID ? bidBar : askBar;
        double price = getPrice(bar, appliedPrice);
        print("T3=%.5f, price=%.5f, bar=%s", prevT3, price, bar);
    }
    
    private double getPrice(IBar bar, AppliedPrice appliedPrice){
        switch (appliedPrice) {
        case CLOSE:
            return bar.getClose();
        case HIGH:
            return bar.getHigh();
        case LOW:
            return bar.getLow();
        case OPEN:
            return bar.getOpen();
        case MEDIAN_PRICE:
            return (bar.getHigh() + bar.getLow()) / 2d;
        case TYPICAL_PRICE:
            return (bar.getHigh() + bar.getLow() + bar.getClose()) / 3d;
        case WEIGHTED_CLOSE:
            return (bar.getHigh() + bar.getLow() + bar.getClose() + bar.getOpen()) / 4d;
        case TIMESTAMP:
            return bar.getTime();
        case VOLUME:
            return bar.getVolume();
        }    
        return 0d;
    }
    
    private void addToChart(IChart chart, IIndicator indicator, Object[] optInputs){
        if(chart == null){
            print("Won't plot indicator on chart. Chart not opened!");    
            return;
        } 
        if (chart.getSelectedOfferSide() != this.side) {
            print("Won't plot indicator on chart. Chart offer side is not " + this.side);
            return;
        }  
        if (chart.getSelectedPeriod() != this.period) {
            print("Won't plot indicator on chart. Chart period is not " + this.period);
            return;
        }         

        chart.addIndicator(indicator, optInputs);
        
        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);
    }
    
    private void print(String format, Object...args){
        print(String.format(format, args));
    }

    private void print(Object message) {
        console.getOut().println(message);
    }

    public void onAccount(IAccount account) throws JFException {    }
    public void onMessage(IMessage message) throws JFException {    }
    public void onStop() throws JFException {    }
    public void onTick(Instrument instrument, ITick tick) throws JFException {    }

}
