package com.dukascopy.visualforex.visualjforex;

import java.util.*;
import com.dukascopy.api.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.CopyOnWriteArrayList;
import java.lang.reflect.*;
import java.math.BigDecimal;


/*
 * Created by VisualJForex Generator, version 2.35
 * Date: 23.11.2016 20:49
 */
public class support_and_resistance implements IStrategy {

	private CopyOnWriteArrayList<TradeEventAction> tradeEventActions = new CopyOnWriteArrayList<TradeEventAction>();
	private static final String DATE_FORMAT_NOW = "yyyyMMdd_HHmmss";
	private IEngine engine;
	private IConsole console;
	private IHistory history;
	private IContext context;
	private IIndicators indicators;
	private IUserInterface userInterface;

	@Configurable("defaultSlippage:")
	public int defaultSlippage = 5;
	@Configurable("defaultTakeProfit:")
	public int defaultTakeProfit = 50;
	@Configurable("defaultPeriod:")
	public Period defaultPeriod = Period.ONE_HOUR;
	@Configurable("defaultTradeAmount:")
	public double defaultTradeAmount = 0.001;
	@Configurable("defaultStopLoss:")
	public int defaultStopLoss = 25;
	@Configurable("defaultInstrument:")
	public Instrument defaultInstrument = Instrument.GBPJPY;

	private String AccountCurrency = "";
	private double _spread;
	private double Leverage;
	private double _short_stop;
	private double _long_stop;
	private Tick LastTick =  null ;
	private double _minimums14;
	private double _NewAmount = 1.5;
	private double _maximums14;
	private double _short_profit;
	private String AccountId = "";
	private double Equity;
	private double UseofLeverage;
	private List<IOrder> PendingPositions =  null ;
	private int _corant;
	private double _risque;
	private List<IOrder> AllPositions =  null ;
	private IOrder _OPEN =  null ;
	private int OverWeekendEndLeverage;
	private int MarginCutLevel;
	private Candle LastAskCandle =  null ;
	private IOrder _pending =  null ;
	private double _long_profit;
	private boolean GlobalAccount;
	private List<IOrder> OpenPositions =  null ;
	private IMessage LastTradeEvent =  null ;
	private Candle LastBidCandle =  null ;


	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();

		subscriptionInstrumentCheck(defaultInstrument);

		ITick lastITick = context.getHistory().getLastTick(defaultInstrument);
		LastTick = new Tick(lastITick, defaultInstrument);

		IBar bidBar = context.getHistory().getBar(defaultInstrument, defaultPeriod, OfferSide.BID, 1);
		IBar askBar = context.getHistory().getBar(defaultInstrument, defaultPeriod, OfferSide.ASK, 1);
		LastAskCandle = new Candle(askBar, defaultPeriod, defaultInstrument, OfferSide.ASK);
		LastBidCandle = new Candle(bidBar, defaultPeriod, defaultInstrument, OfferSide.BID);

		if (indicators.getIndicator("S&R") == null) {
			indicators.registerDownloadableIndicator("6927","SandR");
		}
		subscriptionInstrumentCheck(Instrument.fromString("GBP/JPY"));

		subscriptionInstrumentCheck(Instrument.fromString("GBP/JPY"));

		subscriptionInstrumentCheck(Instrument.fromString("GBP/JPY"));

		subscriptionInstrumentCheck(Instrument.fromString("GBP/JPY"));

		subscriptionInstrumentCheck(Instrument.fromString("GBP/JPY"));

	}

	public void onAccount(IAccount account) throws JFException {
		AccountCurrency = account.getCurrency().toString();
		Leverage = account.getLeverage();
		AccountId= account.getAccountId();
		Equity = account.getEquity();
		UseofLeverage = account.getUseOfLeverage();
		OverWeekendEndLeverage = account.getOverWeekEndLeverage();
		MarginCutLevel = account.getMarginCutLevel();
		GlobalAccount = account.isGlobal();
	}

	private void updateVariables(Instrument instrument) {
		try {
			AllPositions = engine.getOrders();
			List<IOrder> listMarket = new ArrayList<IOrder>();
			for (IOrder order: AllPositions) {
				if (order.getState().equals(IOrder.State.FILLED)){
					listMarket.add(order);
				}
			}
			List<IOrder> listPending = new ArrayList<IOrder>();
			for (IOrder order: AllPositions) {
				if (order.getState().equals(IOrder.State.OPENED)){
					listPending.add(order);
				}
			}
			OpenPositions = listMarket;
			PendingPositions = listPending;
		} catch(JFException e) {
			e.printStackTrace();
		}
	}

	public void onMessage(IMessage message) throws JFException {
		if (message.getOrder() != null) {
			updateVariables(message.getOrder().getInstrument());
			LastTradeEvent = message;
			for (TradeEventAction event :  tradeEventActions) {
				IOrder order = message.getOrder();
				if (order != null && event != null && message.getType().equals(event.getMessageType())&& order.getLabel().equals(event.getPositionLabel())) {
					Method method;
					try {
						method = this.getClass().getDeclaredMethod(event.getNextBlockId(), Integer.class);
						method.invoke(this, new Integer[] {event.getFlowId()});
					} catch (SecurityException e) {
							e.printStackTrace();
					} catch (NoSuchMethodException e) {
						  e.printStackTrace();
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (InvocationTargetException e) {
						e.printStackTrace();
					} 
					tradeEventActions.remove(event); 
				}
			}   
			MultipleAction_block_41(2);
		}
	}

	public void onStop() throws JFException {
	}

	public void onTick(Instrument instrument, ITick tick) throws JFException {
		LastTick = new Tick(tick, instrument);
		updateVariables(instrument);

			If_block_10(0);

	}

	public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
		LastAskCandle = new Candle(askBar, period, instrument, OfferSide.ASK);
		LastBidCandle = new Candle(bidBar, period, instrument, OfferSide.BID);
		updateVariables(instrument);

	}

    public void subscriptionInstrumentCheck(Instrument instrument) {
		try {
		      if (!context.getSubscribedInstruments().contains(instrument)) {
		          Set<Instrument> instruments = new HashSet<Instrument>();
		          instruments.add(instrument);
		          context.setSubscribedInstruments(instruments, true);
		          Thread.sleep(100);
		      }
		  } catch (InterruptedException e) {
		      e.printStackTrace();
		  }
		}

    public double round(double price, Instrument instrument) {
		BigDecimal big = new BigDecimal("" + price); 
		big = big.setScale(instrument.getPipScale() + 1, BigDecimal.ROUND_HALF_UP); 
		return big.doubleValue(); 
	}

    public ITick getLastTick(Instrument instrument) {
		try { 
			return (context.getHistory().getTick(instrument, 0)); 
		} catch (JFException e) { 
			 e.printStackTrace();  
		 } 
		 return null; 
	}

	private  void If_block_10(Integer flow) {
		Instrument argument_1 = LastTick.getInstrument();
		Instrument argument_2 = Instrument.GBPJPY;
		if (argument_1 == null && argument_2 !=null || (argument_1!= null && !argument_1.equals(argument_2))) {
		}
		else if (argument_1!= null && argument_1.equals(argument_2)) {
			GetTimeUnit_block_12(flow);
		}
	}

	private  void GetTimeUnit_block_12(Integer flow) {
		long argument_1 = LastTick.getTime();
		Date date = new Date(argument_1);
		Calendar calendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
		calendar.setTime(date);
		_corant = calendar.get(Calendar.MINUTE);
		If_block_13(flow);
	}

	private  void If_block_13(Integer flow) {
		int argument_1 = _corant;
		int argument_2 = 0;
		if (argument_1< argument_2) {
		}
		else if (argument_1> argument_2) {
			SandR_block_14(flow);
		}
		else if (argument_1== argument_2) {
			If_block_30(flow);
		}
	}

	private void SandR_block_14(Integer flow) {
		Instrument argument_1 = Instrument.GBPJPY;
		Period argument_2 = Period.ONE_HOUR;
		int argument_3 = 2;
		OfferSide[] offerside = new OfferSide[1];
		IIndicators.AppliedPrice[] appliedPrice = new IIndicators.AppliedPrice[1];
		offerside[0] = OfferSide.BID;
		appliedPrice[0] = IIndicators.AppliedPrice.CLOSE;
		Object[] params = new Object[0];
		try {
			subscriptionInstrumentCheck(argument_1);
			long time = context.getHistory().getBar(argument_1, argument_2, OfferSide.BID, argument_3).getTime();
			Object[] indicatorResult = context.getIndicators().calculateIndicator(argument_1, argument_2, offerside,
					"S&R", appliedPrice, params, Filter.WEEKENDS, 1, time, 0);
			if ((new Double(((double [])indicatorResult[0])[0])) == null) {
				this._maximums14 = Double.NaN;
			} else { 
				this._maximums14 = (((double [])indicatorResult[0])[0]);
			} 
			if ((new Double(((double [])indicatorResult[1])[0])) == null) {
				this._minimums14 = Double.NaN;
			} else { 
				this._minimums14 = (((double [])indicatorResult[1])[0]);
			} 
		MultipleAction_block_15(flow);
		} catch (JFException e) {
			e.printStackTrace();
			console.getErr().println(e);
			this._maximums14 = Double.NaN;
			this._minimums14 = Double.NaN;
		}
	}

	private  void MultipleAction_block_15(Integer flow) {
		If_block_19(flow);
		If_block_18(flow);
	}

	private  void If_block_16(Integer flow) {
		int argument_1 = AllPositions.size();
		int argument_2 = 1;
		if (argument_1< argument_2) {
			PendingOpen_block_29(flow);
		}
		else if (argument_1> argument_2) {
		}
		else if (argument_1== argument_2) {
		}
	}

	private  void If_block_17(Integer flow) {
		int argument_1 = AllPositions.size();
		int argument_2 = 1;
		if (argument_1< argument_2) {
			PendingOpen_block_28(flow);
		}
		else if (argument_1> argument_2) {
		}
		else if (argument_1== argument_2) {
		}
	}

	private  void If_block_18(Integer flow) {
		double argument_1 = LastTick.getBid();
		double argument_2 = _maximums14;
		if (argument_1< argument_2) {
		}
		else if (argument_1> argument_2) {
			CalculationExpression_block_20(flow);
		}
		else if (argument_1== argument_2) {
		}
	}

	private  void If_block_19(Integer flow) {
		double argument_1 = LastTick.getAsk();
		double argument_2 = _minimums14;
		if (argument_1< argument_2) {
			CalculationExpression_block_24(flow);
		}
		else if (argument_1> argument_2) {
		}
		else if (argument_1== argument_2) {
		}
	}

	private void CalculationExpression_block_20(Integer flow) {
		_risque = _maximums14-_minimums14;
		CalculationExpression_block_21(flow);
	}

	private void CalculationExpression_block_21(Integer flow) {
		_spread = (LastTick.getAsk()-LastTick.getBid())*2;
		CalculationExpression_block_22(flow);
	}

	private void CalculationExpression_block_22(Integer flow) {
		_long_profit = (_maximums14+_risque)-_spread;
		CalculationExpression_block_23(flow);
	}

	private void CalculationExpression_block_23(Integer flow) {
		_long_stop = _minimums14-_spread;
		If_block_16(flow);
	}

	private void CalculationExpression_block_24(Integer flow) {
		_risque = _maximums14-_minimums14;
		CalculationExpression_block_25(flow);
	}

	private void CalculationExpression_block_25(Integer flow) {
		_spread = (LastTick.getAsk()-LastTick.getBid())*2;
		CalculationExpression_block_26(flow);
	}

	private void CalculationExpression_block_26(Integer flow) {
		_short_profit = (_minimums14-_risque)+_spread;
		CalculationExpression_block_27(flow);
	}

	private void CalculationExpression_block_27(Integer flow) {
		_short_stop = _maximums14+_spread;
		If_block_17(flow);
	}

	private  void PendingOpen_block_28(Integer flow) {
		double argument_1 = _minimums14;
		Instrument argument_2 = Instrument.GBPJPY;
		double argument_3 = _NewAmount;
		int argument_4 = 0;
		double argument_5 = _short_stop;
		double argument_6 = _short_profit;
		String argument_7 = "";
		long argument_8 = 0;
		IEngine.OrderCommand command = IEngine.OrderCommand.SELLLIMIT;

		double stopLoss = round(argument_5, argument_2);
		double takeProfit = round(argument_6, argument_2);
		
        try {
            String label = getLabel();           
            IOrder order = context.getEngine().submitOrder(label, argument_2, command, argument_3, round(argument_1, argument_2), (double)argument_4, stopLoss, takeProfit, argument_8, argument_7);
		        } catch (JFException e) {
            e.printStackTrace();
        }
	}

	private  void PendingOpen_block_29(Integer flow) {
		double argument_1 = _maximums14;
		Instrument argument_2 = Instrument.GBPJPY;
		double argument_3 = _NewAmount;
		int argument_4 = 0;
		double argument_5 = _long_stop;
		double argument_6 = _long_profit;
		String argument_7 = "";
		long argument_8 = 0;
		IEngine.OrderCommand command = IEngine.OrderCommand.BUYLIMIT;

		double stopLoss = round(argument_5, argument_2);
		double takeProfit = round(argument_6, argument_2);
		
        try {
            String label = getLabel();           
            IOrder order = context.getEngine().submitOrder(label, argument_2, command, argument_3, round(argument_1, argument_2), (double)argument_4, stopLoss, takeProfit, argument_8, argument_7);
		        } catch (JFException e) {
            e.printStackTrace();
        }
	}

	private  void If_block_30(Integer flow) {
		int argument_1 = PendingPositions.size();
		int argument_2 = 1;
		if (argument_1< argument_2) {
		}
		else if (argument_1> argument_2) {
		}
		else if (argument_1== argument_2) {
			PositionsViewer_block_31(flow);
		}
	}

	private  void PositionsViewer_block_31(Integer flow) {
		List<IOrder> argument_1 = PendingPositions;
		for (IOrder order : argument_1){
			if (order.getState() == IOrder.State.OPENED||order.getState() == IOrder.State.FILLED){
				_pending = order;
				CloseandCancelPosition_block_32(flow);
			}
		}
	}

	private  void CloseandCancelPosition_block_32(Integer flow) {
		try {
			if (_pending != null && (_pending.getState() == IOrder.State.OPENED||_pending.getState() == IOrder.State.FILLED)){
				_pending.close();
			}
		} catch (JFException e)  {
			e.printStackTrace();
		}
	}

	private  void If_block_33(Integer flow) {
		String argument_1 = LastTradeEvent.getType().name();
		String argument_2 = "ORDER_CLOSE_OK";
		if (argument_1 == null && argument_2 !=null || (argument_1!= null && !argument_1.equals(argument_2))) {
		}
		else if (argument_1!= null && argument_1.equals(argument_2)) {
			If_block_34(flow);
		}
	}

	private  void If_block_34(Integer flow) {
		double argument_1 = LastTradeEvent.getOrder().getProfitLossInUSD();
		double argument_2 = 0.0;
		if (argument_1< argument_2) {
			Calculation_block_35(flow);
		}
		else if (argument_1> argument_2) {
		}
		else if (argument_1== argument_2) {
		}
	}

	private void Calculation_block_35(Integer flow) {
		double argument_1 = LastTradeEvent.getOrder().getAmount();
		double argument_2 = 1.5;
		_NewAmount = argument_1 * argument_2;
	}

	private  void If_block_36(Integer flow) {
		int argument_1 = OpenPositions.size();
		int argument_2 = 1;
		if (argument_1< argument_2) {
		}
		else if (argument_1> argument_2) {
		}
		else if (argument_1== argument_2) {
			PositionsViewer_block_37(flow);
		}
	}

	private  void PositionsViewer_block_37(Integer flow) {
		List<IOrder> argument_1 = OpenPositions;
		for (IOrder order : argument_1){
			if (order.getState() == IOrder.State.OPENED||order.getState() == IOrder.State.FILLED){
				_OPEN = order;
			}
		}
		If_block_44(flow);
	}

	private  void MultipleAction_block_41(Integer flow) {
		If_block_36(flow);
		If_block_33(flow);
	}

	private  void TrailingStop_block_42(Integer flow) {
		IOrder argument_1 = _OPEN;
		double argument_2 = _long_stop;
		int argument_3 = 70;
		try {
			if (argument_1.isLong()) {
				if ((argument_2 != argument_1.getStopLossPrice()) && (argument_2 != 0) && (argument_1.getState().equals(IOrder.State.OPENED) || argument_1.getState().equals(IOrder.State.FILLED))) {
				argument_1.setStopLossPrice(argument_2, OfferSide.BID, argument_3);
				}
		} else {
				if ((argument_2 != argument_1.getStopLossPrice()) && (argument_2 != 0) && (argument_1.getState().equals(IOrder.State.OPENED) || argument_1.getState().equals(IOrder.State.FILLED))) {
				argument_1.setStopLossPrice(argument_2, OfferSide.ASK, argument_3);
				}
		}
		} catch (JFException e) {
			e.printStackTrace();
		}
	}

	private  void TrailingStop_block_43(Integer flow) {
		IOrder argument_1 = _OPEN;
		double argument_2 = _short_stop;
		int argument_3 = 70;
		try {
			if (argument_1.isLong()) {
				if ((argument_2 != argument_1.getStopLossPrice()) && (argument_2 != 0) && (argument_1.getState().equals(IOrder.State.OPENED) || argument_1.getState().equals(IOrder.State.FILLED))) {
				argument_1.setStopLossPrice(argument_2, OfferSide.BID, argument_3);
				}
		} else {
				if ((argument_2 != argument_1.getStopLossPrice()) && (argument_2 != 0) && (argument_1.getState().equals(IOrder.State.OPENED) || argument_1.getState().equals(IOrder.State.FILLED))) {
				argument_1.setStopLossPrice(argument_2, OfferSide.ASK, argument_3);
				}
		}
		} catch (JFException e) {
			e.printStackTrace();
		}
	}

	private  void If_block_44(Integer flow) {
		boolean argument_1 = _OPEN.isLong();
		boolean argument_2 = true;
		if (argument_1!= argument_2) {
			TrailingStop_block_43(flow);
		}
		else if (argument_1 == argument_2) {
			TrailingStop_block_42(flow);
		}
	}

class Candle  {

    IBar bar;
    Period period;
    Instrument instrument;
    OfferSide offerSide;

    public Candle(IBar bar, Period period, Instrument instrument, OfferSide offerSide) {
        this.bar = bar;
        this.period = period;
        this.instrument = instrument;
        this.offerSide = offerSide;
    }

    public Period getPeriod() {
        return period;
    }

    public void setPeriod(Period period) {
        this.period = period;
    }

    public Instrument getInstrument() {
        return instrument;
    }

    public void setInstrument(Instrument instrument) {
        this.instrument = instrument;
    }

    public OfferSide getOfferSide() {
        return offerSide;
    }

    public void setOfferSide(OfferSide offerSide) {
        this.offerSide = offerSide;
    }

    public IBar getBar() {
        return bar;
    }

    public void setBar(IBar bar) {
        this.bar = bar;
    }

    public long getTime() {
        return bar.getTime();
    }

    public double getOpen() {
        return bar.getOpen();
    }

    public double getClose() {
        return bar.getClose();
    }

    public double getLow() {
        return bar.getLow();
    }

    public double getHigh() {
        return bar.getHigh();
    }

    public double getVolume() {
        return bar.getVolume();
    }
}
class Tick {

    private ITick tick;
    private Instrument instrument;

    public Tick(ITick tick, Instrument instrument){
        this.instrument = instrument;
        this.tick = tick;
    }

    public Instrument getInstrument(){
       return  instrument;
    }

    public double getAsk(){
       return  tick.getAsk();
    }

    public double getBid(){
       return  tick.getBid();
    }

    public double getAskVolume(){
       return  tick.getAskVolume();
    }

    public double getBidVolume(){
        return tick.getBidVolume();
    }

   public long getTime(){
       return  tick.getTime();
    }

   public ITick getTick(){
       return  tick;
    }
}

    protected String getLabel() {
        String label;
        label = "IVF" + getCurrentTime(LastTick.getTime()) + generateRandom(10000) + generateRandom(10000);
        return label;
    }

    private String getCurrentTime(long time) {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
        return sdf.format(time);
    }

    private static String generateRandom(int n) {
        int randomNumber = (int) (Math.random() * n);
        String answer = "" + randomNumber;
        if (answer.length() > 3) {
            answer = answer.substring(0, 4);
        }
        return answer;
    }

    class TradeEventAction {
		private IMessage.Type messageType;
		private String nextBlockId = "";
		private String positionLabel = "";
		private int flowId = 0;

        public IMessage.Type getMessageType() {
            return messageType;
        }

        public void setMessageType(IMessage.Type messageType) {
            this.messageType = messageType;
        }

        public String getNextBlockId() {
            return nextBlockId;
        }

        public void setNextBlockId(String nextBlockId) {
            this.nextBlockId = nextBlockId;
        }
        public String getPositionLabel() {
            return positionLabel;
       }

        public void setPositionLabel(String positionLabel) {
            this.positionLabel = positionLabel;
        }
        public int getFlowId() {
            return flowId;
        }
        public void setFlowId(int flowId) {
            this.flowId = flowId;
        }
    }
}