package jforex;

import java.util.*;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.*;

public class Strategy2 implements IStrategy {
    private IEngine engine;
    private IConsole console;
    private IHistory history;
    private IContext context;
    private IIndicators indicators;
    private IUserInterface userInterface;
    private IOrder myOrder; 
    
    private IEngine.OrderCommand myOrderDirection = null;
    private boolean myCanTrade = true;
    private int counter = 0;
    private long lastTickTime = 0;
    private double tickSize;
            
    @Configurable("Stop Loss to use:")
    public int myStopLoss = 500; 
    @Configurable("Take Profit to use")
    public int myTakeProfit = 55; 
    @Configurable("breakEven pips")     
    public int breakEvenPips = 25;
    
    public Instrument myInstrument = Instrument.EURUSD;  
    public Period myPeriod = Period.ONE_MIN;      
    public double myPositionValue = 0.01; 
                                                                                                                
    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();
        this.userInterface = context.getUserInterface();
        lastTickTime = history.getLastTick(myInstrument).getTime();        
        tickSize = Math.pow(10, -myInstrument.getPipScale());
        if (tickSize == 0.001 || tickSize == 0.00001)
            tickSize *= 10;        
    }

    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 {
        double originalSL
             , increment;

        if( (instrument != this.myInstrument) || ((tick.getTime() - lastTickTime) < 1000) )
            return;

        lastTickTime = tick.getTime();

//        print(sdf.format(tick.getTime()) + "trailing SL start");
        for (IOrder order : engine.getOrders())
        {
            if (order.getState() != IOrder.State.FILLED)
                return;                                
        
            if (order.getProfitLossInPips() > breakEvenPips)
            {
                originalSL = order.getStopLossPrice();
                if (engine.getOrder(order.getLabel()).isLong())
                {
                    increment = order.getOpenPrice() + (breakEvenPips*tickSize);
//                    print("Trailing SL check for LONG %s: originalSL(%f) == increment(%f)", order.getLabel(), originalSL, increment);
                    if (originalSL == increment) // check if we already modified the SL
                    {
//                        print("Trailing SL already activated for LONG %s (SL=%f)", order.getLabel(), order.getStopLossPrice());
                        continue;
                    }
                    else
                        order.setStopLossPrice(order.getOpenPrice() + (breakEvenPips*tickSize));
                }
                else
                {
                    increment = order.getOpenPrice() - (breakEvenPips*tickSize);                    
//                    print("Trailing SL check for SHORT %s: originalSL(%f) == increment(%f)", order.getLabel(), originalSL, increment);                    
                    if (originalSL == increment) // check if we already modified the SL
                    {
//                        print("Trailing SL already activated for SHORT %s (SL=%f)", order.getLabel(), order.getStopLossPrice());
                        continue;
                    }
                    else    
                        order.setStopLossPrice(order.getOpenPrice() - (breakEvenPips*tickSize));
                }
                    
                order.waitForUpdate(2000);
//                print("Trailing SL activated for %s. Open price=%.5f. Old SL=%.5f. New SL=%.5f", order.getLabel(), order.getOpenPrice(), originalSL, order.getStopLossPrice());
            }            
        }                                
    }
    
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
         if (myCanTrade && instrument == myInstrument && period == myPeriod){
             int random = (int) (Math.random() * 2);
             
             if (random == 0){
                 myOrderDirection = OrderCommand.BUY;
                 double stopLossPrice = history.getLastTick(myInstrument)
                         .getBid() - myInstrument.getPipValue() * myStopLoss;
                 double takeProfitPrice = history.getLastTick(myInstrument)
                         .getBid() + myInstrument.getPipValue() * myTakeProfit;
                 placeBuyorSell(myOrderDirection, stopLossPrice, takeProfitPrice);
             }else{
                 myOrderDirection = OrderCommand.SELL;
                 double stopLossPrice = history.getLastTick(myInstrument)
                         .getAsk() + myInstrument.getPipValue() * myStopLoss;
                 double takeProfitPrice = history.getLastTick(myInstrument)
                         .getAsk() - myInstrument.getPipValue() * myTakeProfit;
                 placeBuyorSell(myOrderDirection, stopLossPrice, takeProfitPrice);                 
             }
         }               
    }

    private String getLabel (Instrument instrument) throws JFException{
        String label;
        String stripSlash = instrument.toString();
        String[] stripped = stripSlash.split("/");
        String instrumentName = stripped[0] + stripped[1];
        Calendar now = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
        
        String nowYear = "" + now.get(Calendar.YEAR);
        String nowMonth =  "00" + now.get(Calendar.MONTH); //leading 0 if needed
        String nowDay = "00" + now.get(Calendar.DAY_OF_MONTH);
        String nowHours = "00" + now.get(Calendar.HOUR_OF_DAY);
        String nowMinutes = "00" + now.get(Calendar.MINUTE);
        
        label = instrumentName + (counter++) + "_" + nowYear +
                nowMonth.substring(nowMonth.length()- 2) + // get only the last 
                nowDay.substring(nowDay.length() - 2) +  // two digits of 
                nowHours.substring(nowHours.length() - 2) + // the string
                nowMinutes.substring(nowMinutes.length() - 2);
        return label;
    }// end getLabel
    
    private void placeBuyorSell(OrderCommand myOrderCommand, double stopLossPrice, double takeProfitPrice) throws JFException{

        //buy @ price market and with 0.0 slippage
        if (myOrderCommand == OrderCommand.BUY && myCanTrade){
            myOrder = engine.submitOrder(getLabel(myInstrument), myInstrument, 
                    myOrderCommand, myPositionValue, 0, 0, stopLossPrice, 
                    takeProfitPrice);
        }
        //sell @ price market and with 0.0 slippage
        if (myOrderCommand == OrderCommand.SELL && myCanTrade){
            myOrder = engine.submitOrder(getLabel(myInstrument), myInstrument, 
                    myOrderCommand, myPositionValue, 0, 0, stopLossPrice,
                    takeProfitPrice);
        }
    }// end placeBuyorSell
        
}