import com.dukascopy.api.Configurable;
import com.dukascopy.api.IAccount;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IConsole;
import com.dukascopy.api.IContext;
import com.dukascopy.api.IEngine;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.IHistory;
import com.dukascopy.api.IMessage;
import com.dukascopy.api.IOrder;
import com.dukascopy.api.IStrategy;
import com.dukascopy.api.ITick;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.JFException;
import com.dukascopy.api.Period;

public class Order_BS_Stat_RetractionWins_Pending_Hedges_X1 implements IStrategy {


    private IEngine engine;
    private IConsole console;
    private int counter = 0;
    private IHistory history;
    private String string = "";

    @Configurable("Instrument")
    public Instrument instrument = Instrument.EURUSD;

    @Configurable("Slippage")
    public double slippage = 2;
    
    @Configurable("Amount")
    public double amount = 0.1;

    @Configurable("Take Profit Pips")
    public int takeProfitPips = 20;

    @Configurable("Stop Loss Pips")
    public int slPips = 0;

    @Configurable("Hedge Pending ORD Pips")
    public int hedgePending = 20;

    @Configurable("Start Buing")
    public boolean startBuing = true;

    @Configurable("Start Buing")
    public boolean startSelling = false;

    @Override
    public void onStart(IContext context) throws JFException {
        this.console = context.getConsole();
        this.engine = context.getEngine();
        this.setHistory(context.getHistory());


        if(startSelling){
        if (tradesTotalSELL(instrument) == 0) {
            string = "SELL@Market"+counter;
            submitOrder(OrderCommand.SELL, instrument);
            string = "SELL_Stop_ORD"+counter;
            submitOrderStop(OrderCommand.BUY, instrument);
        }}
        if(startBuing){
        if (tradesTotalBUY(instrument) == 0) {
            string = "BUY@Market"+counter;
            submitOrder(OrderCommand.BUY, instrument);
            string = "SELL_Stop_ORD"+counter;
            submitOrderStop(OrderCommand.SELL, instrument);
        }}

    
    }

    @Override
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
        if (instrument != this.instrument) {
            return;
        }
    }

    public void onTick(Instrument instrument, ITick tick) throws JFException {
        
        if (instrument != this.instrument) {
            return;
        }
        for (IOrder orderPlus : engine.getOrders()) {
            if (orderPlus.getState() != IOrder.State.CLOSED && orderPlus.getState() != IOrder.State.CANCELED
                    && orderPlus.getProfitLossInPips() >= 20 && orderPlus.isLong()) {
                orderPlus.close();
                string = "BUY_Stop_ORD"+counter;
                submitOrderStop(OrderCommand.BUY, instrument);
            }
            if (orderPlus.getState() != IOrder.State.CLOSED && orderPlus.getState() != IOrder.State.CANCELED
                    && orderPlus.getProfitLossInPips() >= 20 && !orderPlus.isLong()) {
                orderPlus.close();
                string = "SELL_Stop_ORD"+counter;
                submitOrderStop(OrderCommand.SELL, instrument);
            }
        }
        
    }

    private double getPipPrice(double pips) {
        return pips * this.instrument.getPipValue();
    }

    private String getLabel(Instrument instrument) {
        String label = instrument.name();
        label = label + (counter++);
        label = label.toUpperCase();
        return label;
    }

    public void onMessage(IMessage message) throws JFException {
        print(message);
    }

    public void onStop() throws JFException {
    }

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

    public IHistory getHistory() {
        return history;
    }

    public void setHistory(IHistory history) {
        this.history = history;
    }

    private IOrder submitOrder(OrderCommand orderCmd, Instrument instrument) throws JFException {
        double stopLossPrice = 0.0, takeProfitPrice = 0.0;
        if (orderCmd == OrderCommand.BUY) {
            if (slPips > 0) {
                stopLossPrice = history.getLastTick(instrument).getBid() - getPipPrice(slPips);
            }
            if (takeProfitPips > 0) {
                takeProfitPrice = history.getLastTick(instrument).getBid() + getPipPrice(takeProfitPips);
            }
        } else if (orderCmd == OrderCommand.SELL) {
            if (slPips > 0) {
                stopLossPrice = history.getLastTick(instrument).getBid() + getPipPrice(slPips);
            }
            if (takeProfitPips > 0) {
                takeProfitPrice = history.getLastTick(instrument).getBid() - getPipPrice(takeProfitPips);
            }
        }

        return engine.submitOrder(getLabel(instrument), instrument, orderCmd, amount, 0, slippage, stopLossPrice,takeProfitPrice,0,string);
    }
    public void onAccount(IAccount account) throws JFException {
    }

    private IOrder submitOrderStop(OrderCommand orderCmdLimit, Instrument instrument) throws JFException {

        double stopLossPrice = 0.0, takeProfitPrice = 0.0, price = 0.0;
        if (orderCmdLimit == OrderCommand.BUYSTOP) {
            price = history.getLastTick(instrument).getBid() - Instrument.EURUSD.getPipValue() * (hedgePending);
            if (slPips > 0) {
                stopLossPrice = history.getLastTick(instrument).getBid() - getPipPrice(slPips + hedgePending);
            }
            if (takeProfitPips > 0) {
                takeProfitPrice = history.getLastTick(instrument).getBid() + getPipPrice(takeProfitPips - hedgePending);
            }
        } else if (orderCmdLimit == OrderCommand.SELLSTOP) {
            price = history.getLastTick(instrument).getBid() + Instrument.EURUSD.getPipValue() * (hedgePending);
            if (slPips > 0) {
                stopLossPrice = history.getLastTick(instrument).getBid() + getPipPrice(slPips + hedgePending);
            }
            if (takeProfitPips > 0) {
                takeProfitPrice = history.getLastTick(instrument).getBid() - getPipPrice(takeProfitPips - hedgePending);
            }
        }
        return engine.submitOrder(getLabel(instrument), instrument, orderCmdLimit, amount, price, slippage,
                stopLossPrice, takeProfitPrice, 0, string);
    }

    public int tradesTotalBUY(Instrument INS) throws JFException {
        int counter1 = 0;
        for (IOrder ORD : engine.getOrders(INS)) {
            if (ORD.getState() == IOrder.State.FILLED && ORD.isLong()) {
                counter1++;
            }
        }
        return counter1;
    }

    public int tradesTotalSELL(Instrument INS) throws JFException {
        int counter2 = 0;
        for (IOrder ORD : engine.getOrders(INS)) {
            if (ORD.getState() == IOrder.State.FILLED && !ORD.isLong()) {
                counter2++;
            }
        }
        return counter2;
    }

}
