package jforex;

import com.dukascopy.api.*;

import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.concurrent.Callable;


/**
 * MT4JForexClientsBridge - is simple plug-in for Dukascopy JForex platform. It allows trader to
 * transfer trade signals from Metatrader platform to JForex (For example, in cases if a trader
 * has some strategies in MetaTrader), receive notifications from MetaTrader log file and execute those trade signals.
 * <p/>
 * project website:             http://sourceforge.net/projects/mt4dukabridge/
 * project website on google:   http://code.google.com/p/mt4jforexbridge/
 * flash tutorial:              http://www.dukascopy.com/swiss/english/forex/jforex/forum/download/file.php?id=178
 * pdf tutorial:                http://www.dukascopy.com/swiss/english/forex/jforex/forum/download/file.php?id=249
 * youtube tutorial (1.08 ver): http://www.youtube.com/watch?v=DTjEU4Nt1V8
 *
 * @author Cedric Breitenbach, cedric.breitenbach@yahoo.co.uk
 * @version 2.041
 */

@RequiresFullAccess
public class BridgeSecond implements IStrategy {

    private static final String TRANSLATOR_TAB = "MT4 Dukascopy JForex Client's Bridge2";
    private static final String DATE_FORMAT_NOW = "yyyyMMdd_HHmmss";
    private static final String DATE_FORMAT_DURATION = "yyyy/MM/dd HH:mm";
    private IEngine engine;
    private IHistory history;
    private IContext context;

    @Configurable(value = "Log file", obligatory = true)
    public File logFile;
    // For more fast file params, it is the way to hardcore the path to log file, for Examples:
    //public File logFile = new File ("C:\\Program Files\\MetaTrader - Masterforex\\logs\\20090915.log");
    //public File logFile = new File ("C:\\Program Files\\ODL MetaTrader 4\\logs\\20090915.log");    
    //public File logFile = new File ("C:\\Program Files\\MetaTrader - Alpari\\logs\\20090915.log");
    //public File logFile = new File ("C:\\Program Files\\MetaTrader - FXOpen\\logs\\20090915.log");
    //public File logFile = new File ("C:\\Program Files\\JadeFX\\logs\\20090915.log");
    // Slippage - slippage, if negative then default value of 5 pips is used. Slippage is set in pips, you should pass 1, not 0.0001    
    @Configurable(value = "Slippage:")
    public double slippage = 0;
    // To prevent lots, less than min lot amount in JForex, use 
    @Configurable(value = "Check for Minimum Lot Amount:")
    public boolean isMinLotAmount = false;

    // Parameters for all Instrument,
    // user should set - the needed amount lot to him
    @Configurable(value = "EUR/USD Lot Amount Multiplier:")
    public double amountEURUSD = 0.1;
    @Configurable(value = "GBP/USD Lot Amount Multiplier:")
    public double amountGBPUSD = 0.1;
    @Configurable(value = "NZD/USD Lot Amount Multiplier:")
    public double amountNZDUSD = 0.1;
    @Configurable(value = "USD/CHF Lot Amount Multiplier:")
    public double amountUSDCHF = 0.1;
    @Configurable(value = "USD/JPY Lot Amount Multiplier:")
    public double amountUSDJPY = 0.1;
    @Configurable(value = "AUD/CAD Lot Amount Multiplier:")
    public double amountAUDCAD = 0.1;
    @Configurable(value = "AUD/CHF Lot Amount Multiplier:")
    public double amountAUDCHF = 0.1;
    @Configurable(value = "AUD/JPY Lot Amount Multiplier:")
    public double amountAUDJPY = 0.1;
    @Configurable(value = "AUD/NZD Lot Amount Multiplier:")
    public double amountAUDNZD = 0.1;
    @Configurable(value = "AUD/USD Lot Amount Multiplier:")
    public double amountAUDUSD = 0.1;
    @Configurable(value = "CAD/CHF Lot Amount Multiplier:")
    public double amountCADCHF = 0.1;
    @Configurable(value = "CAD/JPY Lot Amount Multiplier:")
    public double amountCADJPY = 0.1;
    @Configurable(value = "CHF/JPY Lot Amount Multiplier:")
    public double amountCHFJPY = 0.1;
    @Configurable(value = "EUR/AUD Lot Amount Multiplier:")
    public double amountEURAUD = 0.1;
    @Configurable(value = "EUR/CAD Lot Amount Multiplier:")
    public double amountEURCAD = 0.1;
    @Configurable(value = "EUR/CHF Lot Amount Multiplier:")
    public double amountEURCHF = 0.1;
    @Configurable(value = "EUR/GBP Lot Amount Multiplier:")
    public double amountEURGBP = 0.1;
    @Configurable(value = "EUR/JPY Lot Amount Multiplier:")
    public double amountEURJPY = 0.1;
    @Configurable(value = "EUR/NOK Lot Amount Multiplier:")
    public double amountEURNOK = 0.1;
    @Configurable(value = "EUR/SEK Lot Amount Multiplier:")
    public double amountEURSEK = 0.1;
    @Configurable(value = "EUR/NZD Lot Amount Multiplier:")
    public double amountEURNZD = 0.1;
    @Configurable(value = "GBP/AUD Lot Amount Multiplier:")
    public double amountGBPAUD = 0.1;
    @Configurable(value = "GBP/CAD Lot Amount Multiplier:")
    public double amountGBPCAD = 0.1;
    @Configurable(value = "GBP/CHF Lot Amount Multiplier:")
    public double amountGBPCHF = 0.1;
    @Configurable(value = "GBP/JPY Lot Amount Multiplier:")
    public double amountGBPJPY = 0.1;
    @Configurable(value = "GBP/NZD Lot Amount Multiplier:")
    public double amountGBPNZD = 0.1;
    @Configurable(value = "USD/CAD Lot Amount Multiplier:")
    public double amountUSDCAD = 0.1;
    @Configurable(value = "USD/NOK Lot Amount Multiplier:")
    public double amountUSDNOK = 0.1;
    @Configurable(value = "USD/SEK Lot Amount Multiplier:")
    public double amountUSDSEK = 0.1;
    @Configurable(value = "USD/SGD Lot Amount Multiplier:")
    public double amountUSDSGD = 0.1;
    @Configurable(value = "NZD/CAD Lot Amount Multiplier:")
    public double amountNZDCAD = 0.1;
    @Configurable(value = "NZD/CHF Lot Amount Multiplier:")
    public double amountNZDCHF = 0.1;
    @Configurable(value = "NZD/JPY Lot Amount Multiplier:")
    public double amountNZDJPY = 0.1;

    private long filePreviousSize = 0;
    private JPanel translatorPane;
    // Metatrader log table    
    private TranslatorTable translatorTable;
    private TranslatorTable jforexTable;
    private Counter counter = new Counter();
    private static long lastRecordTime = 0;
    // define dateformat, which use MetaTrader in log
    DateFormat sdf = new SimpleDateFormat("HH:mm:ss");
    TimeZone tz = Calendar.getInstance().getTimeZone();
    private JCheckBox chbBetterPrice = new JCheckBox("Execute at Equal or Better Price");
    private JCheckBox chbMetaTraderApprove = new JCheckBox("Execute only by MetaTrader Approve   ");
    // Set orders as Limit orders, for better execution
    private JCheckBox chbLimit = new JCheckBox("Force Execute for not-Limit Orders");
    private static boolean isHistoricData = true;

    private Order orderCurrent = null;
    private IOrder plOrder = null;
    private SpinnerModel model = new SpinnerNumberModel(0, //initial value
            0, //min
            100, //max
            0.1);
    private SpinnerModel modelLeverage = new SpinnerNumberModel(100, //initial value
            1, //min
            100, //max
            1); // step
    private SpinnerModel modelMaxOrders = new SpinnerNumberModel(100, //initial value
            1, //min
            100, //max
            1); // step
    private JSpinner spinner = new JSpinner(model);

    private JSpinner leverageSpinner = new JSpinner(modelLeverage);
    private JSpinner maxOrdersSpinner = new JSpinner(modelMaxOrders);
    private JCheckBox chbMaxOrders = new JCheckBox();
    private JCheckBox chbLeverage = new JCheckBox();
    // advanced settings start
    private JButton btnAdvancedSettings = new JButton("Advanced Settings..");
    private JCheckBox chbCheckMaxLotAmount = new JCheckBox();
    private JCheckBox chbCheckWorkDuration = new JCheckBox();
    private JTextField txtMaxLotAmount = new JTextField("0.1");
    private JTextField txtWorkDurationFrom = new JTextField("");
    private JTextField txtWorkDurationTo = new JTextField("");
    // advanced settings end

    private JRadioButton rbMonitor = new JRadioButton("Monitor");
    private JRadioButton rbExecute = new JRadioButton("Execute");
    private boolean isRequoted = false;
    // Current day 
    private int dayNumber = 0;
    private File bridgeLog;
    private File restorationLog;
    private String version = "2.041";

    private ArrayList<String> listRepeatLines = new ArrayList<String>();
    // list of operations, which are corresponde to the orders with status CREATED
    private ArrayList<Operation> listOperations = new ArrayList<Operation>();
    private IAccount account;

    // settings for multiple Bridges, logs files:
    private String bridgesLog = "bridge2.log";
    private String bridgesOldLog = "bridgeOld2.log";
    private String restorationsLog = "restoration2.log";

    public void onStart(IContext context) throws JFException {
        this.engine = context.getEngine();
        this.history = context.getHistory();
        this.context = context;
        this.translatorPane = context.getUserInterface().getBottomTab(TRANSLATOR_TAB);
        this.translatorTable = new TranslatorTable();
        this.jforexTable = new TranslatorTable();

        counter.start();
        buildGui();
    }

    public void onAccount(IAccount account) throws JFException {
        this.account = account;
    }

    public void onMessage(IMessage message) throws JFException {
        if (message.getOrder() != null) {
            Order order = getJForexOrder(jforexTable, message.getOrder().getLabel());
            if (order != null) {
                if (listOperations.size() > 0 && (message.getOrder().getState().toString().equals("OPENED") || message.getOrder().getState().toString().equals("FILLED"))) {
                    processOperation(message.getOrder());
                }
                logEvent("Order " + message.getOrder().getLabel() + " " + message.getOrder().getState());
                order.setStatus("" + message.getOrder().getState());
            }
        }
    }

    public void onStop() throws JFException {
        saveMTConnection();
        logEvent("Bridge Exit");
        counter.stop();
        context.getUserInterface().removeBottomTab(TRANSLATOR_TAB);
    }

    public void onTick(Instrument instrument, ITick tick) throws JFException {

    }

    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {

    }


    // Read MetaTrader Log
    private synchronized void readMetaTraderLog() {
        FileInputStream fis;
        BufferedInputStream bis;
        DataInputStream dis;
        try {
            fis = new FileInputStream(logFile);

            String previousLine = "";
            String strLine = "";
            // Here BufferedInputStream is added for fast reading.
            bis = new BufferedInputStream(fis);
            dis = new DataInputStream(bis);
            // dis.available() returns 0 if the file does not have more lines.
            while (dis.available() != 0) {
                strLine = dis.readLine();
                String f[] = strLine.split(" ");
                //logEvent("temp:: " + strLine + " calculated time " + getCurrTime(sdf.parse(f[0])) + " lastRecordTime " + lastRecordTime);
                // case of instance orders
                if (f != null && f.length > 1) {
                    if (!chbMetaTraderApprove.isSelected()) {
                        if (f.length == 13 && f[2].equals("instant")) {
                            Date date = sdf.parse(f[0]);
                            long dating = getCurrTime(date);
                            if (lastRecordTime <= dating && isNotPrevLine(strLine)) {
                                lastRecordTime = dating;
                                //Order(Instrument instrument, String time, double price, String type, double amount, double takeProfitPrice, double stopLossPrice)
                                String instr = getInstrumentWithoutPrefix(f[6]);
                                if (instr != null) {
                                    Order order = new Order(Instrument.valueOf(instr), f[0], Double.parseDouble(f[8]), f[4], doTranslateAmount(Double.parseDouble(f[5]), instr), Double.parseDouble(f[12]), Double.parseDouble(f[10]));
                                    TranslatorTableModel model = (TranslatorTableModel) translatorTable.getModel();
                                    model.addOrder(order);
                                    if (isInsideDuration() && !isRequoted && !rbMonitor.isSelected() && !isHistoricData && isUseofLeverageOK() && isMaxOrdersOK()) {
                                        logEvent("MetaTrader Instant Order Received " + strLine);
                                        orderCurrent = order;
                                        if (!chbBetterPrice.isSelected() || (chbBetterPrice.isSelected() && isBetterPrice(orderCurrent))) {
                                            DoOrderTask task = new DoOrderTask(getOrderBeforeExecution(orderCurrent, true));
                                            context.executeTask(task);
                                            saveMTConnection();
                                        }
                                    }
                                }
                                isRequoted = false;
                                System.out.println(" instant order: " + f[0]);

                            }
                        } else if (f.length == 11 && f[4].equals("market")) {
                            Date date = sdf.parse(f[0]);
                            if (lastRecordTime <= getCurrTime(date) && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                //Order(Instrument instrument, String time, double price, String type, double amount, double takeProfitPrice, double stopLossPrice)
                                String instr = getInstrumentWithoutPrefix(f[6]);
                                if (instr != null) {
                                    Order order = new Order(Instrument.valueOf(instr), f[0], 0, f[3], doTranslateAmount(Double.parseDouble(f[5]), instr), 0, 0);
                                    TranslatorTableModel model = (TranslatorTableModel) translatorTable.getModel();
                                    model.addOrder(order);
                                    if (isInsideDuration() && !isRequoted && !rbMonitor.isSelected() && !isHistoricData && isUseofLeverageOK() && isMaxOrdersOK()) {
                                        orderCurrent = order;
                                        logEvent("MetaTrader Market Order Received " + strLine);
                                        DoOrderTask task = new DoOrderTask(getOrderBeforeExecution(orderCurrent, false));
                                        context.executeTask(task);
                                        saveMTConnection();
                                    }
                                }
                                isRequoted = false;
                                System.out.println(" market order: " + f[0]);
                            }
                        } else if (f.length == 14 && f[2].equals("pending")) {
                            Date date = sdf.parse(f[0]);
                            if (lastRecordTime <= getCurrTime(date) && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                //Order(Instrument instrument, String time, double price, String type, double amount, double takeProfitPrice, double stopLossPrice)
                                String instr = getInstrumentWithoutPrefix(f[7]);
                                if (instr != null) {
                                    Order order = new Order(Instrument.valueOf(instr), f[0], Double.parseDouble(f[9]), f[4] + " " + f[5], doTranslateAmount(Double.parseDouble(f[6]), instr), Double.parseDouble(f[13]), Double.parseDouble(f[11]));
                                    TranslatorTableModel model = (TranslatorTableModel) translatorTable.getModel();
                                    model.addOrder(order);
                                    if (isInsideDuration() && !isRequoted && !rbMonitor.isSelected() && !isHistoricData && isUseofLeverageOK() && isMaxOrdersOK()) {
                                        orderCurrent = order;
                                        logEvent("MetaTrader Pending Order Received " + strLine);
                                        boolean issetBetter = false;
//                                    if (chbBetterPrice.isSelected()) {                                         
//                                        issetBetter = isBetterPrice(orderCurrent);
//                                    }
                                        DoOrderTask task = new DoOrderTask(getOrderBeforeExecution(orderCurrent, issetBetter));
                                        context.executeTask(task);
                                    }
                                }
                                isRequoted = false;
                                System.out.println(" pending order: " + f[0]);
                                saveMTConnection();
                            }
                        } else
                        if ((f.length == 17 || f.length == 16) && f[2].equals("order") && f[3].equals("was") && f[4].equals("opened")) {
                            Date date = sdf.parse(f[0]);
                            if (isInsideDuration() && !rbMonitor.isSelected() && lastRecordTime <= getCurrTime(date) && !isHistoricData && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                setMetaTraderId(f[6]);
                                logEvent("MetaTrader Order was Opened " + strLine);
                                System.out.println(" order was opened " + f[6]);
                                saveMTConnection();
                            }
                            // order modify
                        } else
                        if (f.length == 23 && f[2].equals("modify") && f[3].equals("pending") && f[4].equals("order")) {
                            Date date = sdf.parse(f[0]);
                            if (isInsideDuration() && !rbMonitor.isSelected() && lastRecordTime <= getCurrTime(date) && !isHistoricData && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                modifyOrder(f[5], Double.parseDouble(f[18]), Double.parseDouble(f[20]), Double.parseDouble(f[22]));
                                logEvent("MetaTrader Modify Pending Order " + strLine);
                                System.out.println(" modify pending order: " + f[5]);
                                saveMTConnection();
                            }
                        } else if (f.length == 19 && f[2].equals("modify") && f[3].equals("order")) {
                            //System.out.println(":: " + !isHistoricData + " 2  " + " 3  "+  isNotPrevLine(strLine));
                            Date date = sdf.parse(f[0]);
                            if (isInsideDuration() && !rbMonitor.isSelected() && lastRecordTime <= getCurrTime(date) && !isHistoricData && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                modifyOrder(f[4], Double.parseDouble(f[16]), Double.parseDouble(f[18]));
                                logEvent("MetaTrader Order Modify " + strLine);
                                System.out.println(" modify order: " + f[4]);
                                saveMTConnection();
                            }
                        } else
                        if (f.length == 16 && f[2].equals("delete") && f[3].equals("pending") && f[4].equals("order") && isNotPrevLine(strLine)) {
                            Date date = sdf.parse(f[0]);
                            if (isInsideDuration() && !rbMonitor.isSelected() && lastRecordTime < getCurrTime(date) && !isHistoricData) {
                                lastRecordTime = getCurrTime(date);
                                deleteOrder(f[5]);
                                logEvent("MetaTrader Order Delete " + strLine);
                                System.out.println(" delete order: " + f[5]);
                                saveMTConnection();
                            }
                        } else if ((f.length == 17 || f.length == 18) && f[2].equals("close") && f[3].equals("order")) {
                            Date date = sdf.parse(f[0]);
                            if (isInsideDuration() && !rbMonitor.isSelected() && lastRecordTime <= getCurrTime(date) && !isHistoricData && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                if (f.length == 17) {
                                    String instr = getInstrumentWithoutPrefix(f[7]);
                                    if (instr != null) {
                                        closeOrder(f[4], doTranslateAmount(Double.parseDouble(f[6]), instr));
                                    }
                                } else {
                                    String instr = getInstrumentWithoutPrefix(f[8]);
                                    if (instr != null) {
                                        closeOrder(f[4], doTranslateAmount(Double.parseDouble(f[6]), instr));
                                    }
                                }
                                logEvent("MetaTrader Order Closed " + strLine);
                                saveMTConnection();
                                System.out.println(" close order: " + f[4]);
                            }
                        } else if (f.length > 4 && f[2].equals("requote")) {
                            Date date = sdf.parse(f[0]);
                            if (lastRecordTime <= getCurrTime(date) && !isHistoricData && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                logEvent("MetaTrader Order Requoted " + strLine);
                                isRequoted = true;
                            }
                        } else
                        if (f.length > 5 && f[2].equals("remainder") && f[3].equals("of") && f[4].equals("order")) {
                            Date date = sdf.parse(f[0]);
                            if (isInsideDuration() && !rbMonitor.isSelected() && (lastRecordTime <= getCurrTime(date)) && !isHistoricData && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                renameOrder(f[5], f[9]);
                                logEvent("MetaTrader Order was Renamed " + strLine);
                                System.out.println("MetaTrader Order was Renamed: " + f[5] + " " + f[9]);
                                saveMTConnection();
                            }
                        }
                        // For MetaTrader approve, do action if MetaTrader Server (not user or strategy) do
                    } else {
                        Date date = sdf.parse(f[0]);
                        if ((f.length == 17 || f.length == 16) && f[2].equals("order") && f[3].equals("was") && f[4].equals("opened")) {
                            //Date date = sdf.parse(f[0]);
                            if (lastRecordTime <= getCurrTime(date) && !isHistoricData && isNotPrevLine(strLine) && isUseofLeverageOK() && isMaxOrdersOK()) {
                                lastRecordTime = getCurrTime(date);
                                Order order = null;
                                if (f.length == 17) {
                                    String instr = getInstrumentWithoutPrefix(f[10]);
                                    if (instr != null) {
                                        order = new Order(Instrument.valueOf(instr), f[0], Double.parseDouble(f[12]), f[7] + " " + f[8], doTranslateAmount(Double.parseDouble(f[9]), instr), Double.parseDouble(f[16]), Double.parseDouble(f[14]));
                                    }
                                } else {
                                    String instr = getInstrumentWithoutPrefix(f[9]);
                                    if (instr != null) {
                                        order = new Order(Instrument.valueOf(instr), f[0], Double.parseDouble(f[11]), f[7], doTranslateAmount(Double.parseDouble(f[8]), instr), Double.parseDouble(f[15]), Double.parseDouble(f[13]));
                                    }
                                }
                                if (order != null) {
                                    TranslatorTableModel model = (TranslatorTableModel) translatorTable.getModel();
                                    setMetaTraderId(f[6], order);
                                    model.addOrder(order);
                                    if (isInsideDuration() && !rbMonitor.isSelected()) {
                                        orderCurrent = order;
                                        logEvent("MetaTrader Order Received " + strLine);

                                        boolean issetBetter = false;
                                        if (f.length == 17) {

                                        } else if (chbBetterPrice.isSelected()) {
                                            issetBetter = isBetterPrice(orderCurrent);
                                        }
                                        DoOrderTask task = new DoOrderTask(getOrderBeforeExecution(orderCurrent, issetBetter));
                                        context.executeTask(task);
                                        saveMTConnection();
                                    }
                                }
                            }
                            // order modify
                        } else
                        if (f.length == 23 && f[2].equals("modify") && f[3].equals("pending") && f[4].equals("order")) {
                            // Date date = sdf.parse(f[0]);
                            if (isInsideDuration() && !rbMonitor.isSelected() && (lastRecordTime <= getCurrTime(date)) && !isHistoricData && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                modifyOrder(f[5], Double.parseDouble(f[18]), Double.parseDouble(f[20]), Double.parseDouble(f[22]));
                                logEvent("MetaTrader Modify Pending Order " + strLine);
                                System.out.println(" modify pending order: " + f[5]);
                                saveMTConnection();
                            }
                        } else if (f.length == 19 && f[2].equals("modify") && f[3].equals("order")) {
                            //Date date = sdf.parse(f[0]);
                            if (isInsideDuration() && !rbMonitor.isSelected() && (lastRecordTime <= getCurrTime(date)) && !isHistoricData && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                modifyOrder(f[4], Double.parseDouble(f[16]), Double.parseDouble(f[18]));
                                logEvent("MetaTrader Order Modify " + strLine);
                                System.out.println(" modify order: " + f[4]);
                                saveMTConnection();
                            }
                        } else
                        if (f.length == 16 && f[2].equals("delete") && f[3].equals("pending") && f[4].equals("order")) {
                            /// Date date = sdf.parse(f[0]);
                            if (isInsideDuration() && !rbMonitor.isSelected() && (lastRecordTime <= getCurrTime(date)) && !isHistoricData && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                deleteOrder(f[5]);
                                logEvent("MetaTrader Order Delete " + strLine);
                                System.out.println(" delete order: " + f[5]);
                                saveMTConnection();
                            }
                        } else if ((f.length == 17 || f.length == 18) && f[2].equals("close") && f[3].equals("order")) {
                            //Date date = sdf.parse(f[0]);
                            if (isInsideDuration() && !rbMonitor.isSelected() && (lastRecordTime <= getCurrTime(date)) && !isHistoricData && isNotPrevLine(strLine)) {
                                lastRecordTime = getCurrTime(date);
                                if (f.length == 17) {
                                    String instr = getInstrumentWithoutPrefix(f[7]);
                                    if (instr != null) {
                                        closeOrder(f[4], doTranslateAmount(Double.parseDouble(f[6]), instr));
                                    }
                                } else {
                                    String instr = getInstrumentWithoutPrefix(f[8]);
                                    if (instr != null) {
                                        closeOrder(f[4], doTranslateAmount(Double.parseDouble(f[6]), instr));
                                    }
                                }
                                saveMTConnection();
                                logEvent("MetaTrader Order Closed " + strLine);
                                System.out.println(" close order: " + f[4]);
                            }
                        } else
                        if (f.length > 5 && f[2].equals("remainder") && f[3].equals("of") && f[4].equals("order")) {
                            // Date date = sdf.parse(f[0]);
                            if (isInsideDuration() && !rbMonitor.isSelected() && (lastRecordTime <= getCurrTime(date)) && !isHistoricData) {
                                lastRecordTime = getCurrTime(date);
                                renameOrder(f[5], f[9]);
                                saveMTConnection();
                                logEvent("MetaTrader Order was Renamed " + strLine);
                                System.out.println("MetaTrader Order was Renamed: " + f[5] + " " + f[9]);
                            }
                        }
                    }

                    // this statement reads the line from the file and print it to
                    // the console.
                    //System.out.println(strLine);

                    //repeatable data process
                    Date date = sdf.parse(f[0]);
                    long dating = getCurrTime(date);
                    if (previousLine != null && previousLine.length() > 0) {
                        String r[] = previousLine.split(" ");
                        Date dateR = sdf.parse(r[0]);
                        long datingR = getCurrTime(dateR);
                        if (dating > datingR && dating > lastRecordTime && isNotPrevLine(strLine)) {
                            clearRepeatableData();
                            lastRecordTime = dating;
                        }
                    }
                    addRepeatableData(strLine);
                    if (lastRecordTime >= dating || lastRecordTime == 0) {
                        previousLine = strLine;
                    }
                }
            }

            if (isHistoricData) {
                lastRecordTime++;
            }

            isHistoricData = false;
            // dispose all the resources after using them.
            fis.close();
            bis.close();
            dis.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    private Order getOrderBeforeExecution(Order order, boolean isBetterPrice) {
        Order orderCurrent;
        //getRoundedPrice
        double price = getRoundedPrice(order.getInstrument(), order.getPrice());
        double priceTakeProfit = getRoundedPrice(order.getInstrument(), order.getTakeProfitPrice());
        double priceStopLoss = getRoundedPrice(order.getInstrument(), order.getStopLossPrice());

        orderCurrent = new Order(order.getInstrument(), order.getTime(), price, order.getType(), order.getAmount(), priceTakeProfit, priceStopLoss);
        if (isBetterPrice) {
            setBetterPrice(orderCurrent);
        }
        if (order.getOrderMetaTraderID().length() > 0) {
            orderCurrent.setOrderMetaTraderID(order.getOrderMetaTraderID());
        }
        orderCurrent.setOrderJForexID(getLabel());
        order.setOrderJForexID(orderCurrent.getOrderJForexID());
        TranslatorTableModel modelJF = (TranslatorTableModel) jforexTable.getModel();
        modelJF.addOrder(orderCurrent);
        return orderCurrent;
    }

    private class DoOrderTask implements Callable<Object> {
        Order orderCurrent;

        public DoOrderTask(Order order) {
            this.orderCurrent = order;
        }

        public Object call() {

            //now we are in strategy thread
            if (orderCurrent != null) {
                try {
                    double slipLocal = slippage;
                    if (slippage == 0) {
                        slipLocal = 20;
                    }
                    if (orderCurrent.getType().equals("sell")) {
                        if (orderCurrent.getTakeProfitPrice() != 0 || orderCurrent.getStopLossPrice() != 0) {
                            if (chbLimit.isSelected()) {
                                double price = history.getLastTick(orderCurrent.getInstrument()).getBid();
                                logEvent("JForex sell submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount() + " price : " + price + " " + orderCurrent.getTakeProfitPrice() + " " + orderCurrent.getStopLossPrice() + " slippage : " + slipLocal);
                                plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.SELLLIMIT, isMinimumLotAmount(orderCurrent.getAmount()), price, slipLocal, orderCurrent.getStopLossPrice(), orderCurrent.getTakeProfitPrice());
                            } else {
                                logEvent("JForex sell submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount() + " " + orderCurrent.getTakeProfitPrice() + " " + orderCurrent.getStopLossPrice() + " slippage : " + slippage);
                                plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.SELL, isMinimumLotAmount(orderCurrent.getAmount()), 0, slippage, orderCurrent.getStopLossPrice(), orderCurrent.getTakeProfitPrice());
                            }
                        } else {
                            if (chbLimit.isSelected()) {
                                double price = history.getLastTick(orderCurrent.getInstrument()).getBid();
                                logEvent("JForex sell submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount() + " price : " + price + " slippage : " + slipLocal);
                                plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.SELLLIMIT, isMinimumLotAmount(orderCurrent.getAmount()), price, slipLocal);
                            } else {
                                logEvent("JForex sell submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount());
                                plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.SELL, isMinimumLotAmount(orderCurrent.getAmount()), 0, slippage);
                            }
                        }
                    } else if (orderCurrent.getType().equals("buy")) {
                        if (orderCurrent.getTakeProfitPrice() != 0 || orderCurrent.getStopLossPrice() != 0) {
                            if (chbLimit.isSelected()) {
                                double price = history.getLastTick(orderCurrent.getInstrument()).getAsk();
                                logEvent("JForex buy submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount() + " price : " + price + " " + orderCurrent.getTakeProfitPrice() + " " + orderCurrent.getStopLossPrice() + " slippage : " + slipLocal);
                                plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.BUYLIMIT, isMinimumLotAmount(orderCurrent.getAmount()), price, slipLocal, orderCurrent.getStopLossPrice(), orderCurrent.getTakeProfitPrice());
                            } else {
                                logEvent("JForex buy submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount() + " " + orderCurrent.getTakeProfitPrice() + " " + orderCurrent.getStopLossPrice() + " slippage : " + slippage);
                                plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.BUY, isMinimumLotAmount(orderCurrent.getAmount()), 0, slippage, orderCurrent.getStopLossPrice(), orderCurrent.getTakeProfitPrice());
                            }
                        } else {
                            if (chbLimit.isSelected()) {
                                double price = history.getLastTick(orderCurrent.getInstrument()).getAsk();
                                logEvent("JForex buy submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount() + " price : " + price + " slippage : " + slipLocal);
                                plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.BUYLIMIT, isMinimumLotAmount(orderCurrent.getAmount()), price, slipLocal);
                            } else {
                                logEvent("JForex buy submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount());
                                plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.BUY, isMinimumLotAmount(orderCurrent.getAmount()), 0, slippage);
                            }
                        }
                    } else if (orderCurrent.getType().equals("buy stop")) {
                        logEvent("JForex buy stop submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount() + " price : " + orderCurrent.getPrice() + " " + orderCurrent.getTakeProfitPrice() + " " + orderCurrent.getStopLossPrice() + " slippage : " + slippage);
                        plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.BUYSTOP, isMinimumLotAmount(orderCurrent.getAmount()), orderCurrent.getPrice(), slippage, orderCurrent.getStopLossPrice(), orderCurrent.getTakeProfitPrice());
                    } else if (orderCurrent.getType().equals("buy limit")) {
                        logEvent("JForex buy limit submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount() + " price : " + orderCurrent.getPrice() + " " + orderCurrent.getTakeProfitPrice() + " " + orderCurrent.getStopLossPrice() + " slippage : " + slippage);
                        plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.BUYLIMIT, isMinimumLotAmount(orderCurrent.getAmount()), orderCurrent.getPrice(), slippage, orderCurrent.getStopLossPrice(), orderCurrent.getTakeProfitPrice());
                    } else if (orderCurrent.getType().equals("sell limit")) {
                        logEvent("JForex sell limit submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount() + " price : " + orderCurrent.getPrice() + " " + orderCurrent.getTakeProfitPrice() + " " + orderCurrent.getStopLossPrice() + " slippage : " + slippage);
                        plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.SELLLIMIT, isMinimumLotAmount(orderCurrent.getAmount()), orderCurrent.getPrice(), slippage, orderCurrent.getStopLossPrice(), orderCurrent.getTakeProfitPrice());
                    } else if (orderCurrent.getType().equals("sell stop")) {
                        logEvent("JForex sell stop submit order :: " + orderCurrent.getOrderJForexID() + " : " + orderCurrent.getInstrument() + " amount :: " + orderCurrent.getAmount() + " price : " + orderCurrent.getPrice() + " " + orderCurrent.getTakeProfitPrice() + " " + orderCurrent.getStopLossPrice() + " slippage : " + slippage);
                        plOrder = engine.submitOrder(orderCurrent.getOrderJForexID(), orderCurrent.getInstrument(), IEngine.OrderCommand.SELLSTOP, isMinimumLotAmount(orderCurrent.getAmount()), orderCurrent.getPrice(), slippage, orderCurrent.getStopLossPrice(), orderCurrent.getTakeProfitPrice());
                    }
                } catch (JFException ejf) {
                    ejf.printStackTrace();
                }
                orderCurrent = null;
            }
            return null;
        }
    }

    private double doTranslateAmount(double amount, String instrument) {
        if ("EURUSD".equals(instrument)) {
            amount = amount * amountEURUSD;
        } else if ("GBPUSD".equals(instrument)) {
            amount = amount * amountGBPUSD;
        } else if ("NZDUSD".equals(instrument)) {
            amount = amount * amountNZDUSD;
        } else if ("USDCHF".equals(instrument)) {
            amount = amount * amountUSDCHF;
        } else if ("USDJPY".equals(instrument)) {
            amount = amount * amountUSDJPY;
        } else if ("AUDJPY".equals(instrument)) {
            amount = amount * amountAUDJPY;
        } else if ("AUDNZD".equals(instrument)) {
            amount = amount * amountAUDNZD;
        } else if ("AUDUSD".equals(instrument)) {
            amount = amount * amountAUDUSD;
        } else if ("CADJPY".equals(instrument)) {
            amount = amount * amountCADJPY;
        } else if ("CHFJPY".equals(instrument)) {
            amount = amount * amountCHFJPY;
        } else if ("EURAUD".equals(instrument)) {
            amount = amount * amountEURAUD;
        } else if ("EURCAD".equals(instrument)) {
            amount = amount * amountEURCAD;
        } else if ("EURCHF".equals(instrument)) {
            amount = amount * amountEURCHF;
        } else if ("EURGBP".equals(instrument)) {
            amount = amount * amountEURGBP;
        } else if ("EURJPY".equals(instrument)) {
            amount = amount * amountEURJPY;
        } else if ("EURNOK".equals(instrument)) {
            amount = amount * amountEURNOK;
        } else if ("EURSEK".equals(instrument)) {
            amount = amount * amountEURSEK;
        } else if ("GBPCHF".equals(instrument)) {
            amount = amount * amountGBPCHF;
        } else if ("GBPJPY".equals(instrument)) {
            amount = amount * amountGBPJPY;
        } else if ("USDCAD".equals(instrument)) {
            amount = amount * amountUSDCAD;
        } else if ("USDCAD".equals(instrument)) {
            amount = amount * amountUSDCAD;
        } else if ("USDNOK".equals(instrument)) {
            amount = amount * amountUSDNOK;
        } else if ("USDSEK".equals(instrument)) {
            amount = amount * amountUSDSEK;
        } else if ("USDSGD".equals(instrument)) {
            amount = amount * amountUSDSGD;
        } else if ("AUDCAD".equals(instrument)) {
            amount = amount * amountAUDCAD;
        } else if ("AUDCHF".equals(instrument)) {
            amount = amount * amountAUDCHF;
        } else if ("CADCHF".equals(instrument)) {
            amount = amount * amountCADCHF;
        } else if ("EURNZD".equals(instrument)) {
            amount = amount * amountEURNZD;
        } else if ("GBPAUD".equals(instrument)) {
            amount = amount * amountGBPAUD;
        } else if ("GBPCAD".equals(instrument)) {
            amount = amount * amountGBPCAD;
        } else if ("GBPNZD".equals(instrument)) {
            amount = amount * amountGBPNZD;
        } else if ("NZDCAD".equals(instrument)) {
            amount = amount * amountNZDCAD;
        } else if ("NZDCHF".equals(instrument)) {
            amount = amount * amountNZDCHF;
        } else if ("NZDJPY".equals(instrument)) {
            amount = amount * amountNZDJPY;
        }
        return amount;
    }

    // Check if Metatrader log was updated
    private boolean isLogUpdated() {
        setAutomaticLogFile();
        if (logFile.length() != filePreviousSize) {
            filePreviousSize = logFile.length();
            //System.out.println("The Log was changed");
            return true;
        }
        //else if (isHistoricData){
        //    return true;
        //}
        return false;
    }

    // Thread need to check file with sleep
    private class Counter extends Thread {
        public void run() {
            try {
                while (Thread.currentThread().isAlive()) {
                    sleep(300);
                    if (isLogUpdated()) {
                        readMetaTraderLog();
                    }
                }
            } catch (InterruptedException e) {
                stop();
                e.printStackTrace();
            }
        }
    }

    private void buildGui() {
        // create log file
        try {
            String currentLogPath = logFile.getAbsolutePath().substring(0, logFile.getAbsolutePath().length() - 12);
            bridgeLog = new File(currentLogPath + bridgesLog);
            if (!bridgeLog.exists()) {
                bridgeLog.createNewFile();
            } else {
                // File (or directory) with new name
                File bridgeLogOLD = new File(currentLogPath + bridgesOldLog);
                copy(bridgeLog, bridgeLogOLD);
                boolean success = bridgeLog.delete();
                bridgeLog = new File(currentLogPath + bridgesLog);
                bridgeLog.createNewFile();
            }
            logEvent("Bridge is Started, version " + version + " user " + engine.getAccount());
        } catch (IOException e) {
            e.printStackTrace();
        }
        createMTRestoreFile();

        lastRecordTime = 0;

        //Group the radio buttons.
        ButtonGroup group = new ButtonGroup();
        group.add(rbMonitor);
        group.add(rbExecute);
        rbMonitor.setSelected(true);
        spinner.setEnabled(false);

        initAdvancedSettings();

        chbBetterPrice.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (chbBetterPrice.isSelected()) {
                    spinner.setEnabled(true);
                    chbLimit.setEnabled(false);
                } else {
                    spinner.setEnabled(false);
                    chbLimit.setEnabled(true);
                }
            }
        });

        chbMetaTraderApprove.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (chbMetaTraderApprove.isSelected()) {
                    lastRecordTime++;
                    logEvent("Bridge is Set - Execute only by MetaTrader Approve");
                } else {
                    lastRecordTime++;
                    logEvent("Bridge is Set - Execute Signals without MetaTrader Approve");
                }
            }
        });

        chbLimit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (chbLimit.isSelected()) {
                    logEvent("Always Execute - setting is Set");
                    chbBetterPrice.setEnabled(false);
                } else {
                    chbBetterPrice.setEnabled(true);
                    logEvent("Always Execute - setting is Remove");
                }
            }
        });

        chbBetterPrice.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (chbBetterPrice.isSelected()) {
                    logEvent("Better Prise - setting is Set");
                } else {
                    logEvent("Better Prise - setting is Remove");
                }
            }
        });

        chbLeverage.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (chbLeverage.isSelected()) {
                    leverageSpinner.setEnabled(true);
                    logEvent("Max Use of Leverage - setting is Set " + leverageSpinner.getValue());
                } else {
                    leverageSpinner.setEnabled(false);
                    logEvent("Max Use of Leverage - setting is Remove " + leverageSpinner.getValue());
                }
            }
        });

        chbMaxOrders.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (chbMaxOrders.isSelected()) {
                    maxOrdersSpinner.setEnabled(true);
                    logEvent("Max Orders - setting is Set " + maxOrdersSpinner.getValue());
                } else {
                    maxOrdersSpinner.setEnabled(false);
                    logEvent("Max Orders - setting is Remove " + maxOrdersSpinner.getValue());
                }
            }
        });

        btnAdvancedSettings.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showAdvancedSettings();
            }
        });

        translatorPane.setLayout(new BorderLayout());

        //translatorPane.setLayout(new FlowLayout(FlowLayout.LEADING));
        JPanel container = new JPanel();
        container.setLayout(new FlowLayout(FlowLayout.LEADING));

        JScrollPane scrollPane = new JScrollPane(translatorTable);
        JScrollPane scrollPane2 = new JScrollPane(jforexTable);
        JPanel panelMeta = new JPanel(new BorderLayout());
        JPanel panelJForex = new JPanel(new BorderLayout());

        panelMeta.add(new JLabel("        MetaTrader"), BorderLayout.PAGE_START);
        panelMeta.add(scrollPane, BorderLayout.CENTER);
        container.add(panelMeta);
        panelJForex.add(new JLabel("       JForex"), BorderLayout.PAGE_START);
        panelJForex.add(scrollPane2, BorderLayout.CENTER);
        container.add(panelJForex);

        JPanel radioBtPanel = new JPanel();
        radioBtPanel.add(rbMonitor);
        radioBtPanel.add(rbExecute);

        JPanel betterPricePanel = new JPanel();
        betterPricePanel.setBackground(new Color(200, 200, 240));
        betterPricePanel.add(chbBetterPrice);
        betterPricePanel.add(new JLabel("Pips Amount Diff.:"));
        betterPricePanel.add(spinner);

        JPanel forceExecPanel = new JPanel();
        forceExecPanel.setBackground(Color.WHITE);
        forceExecPanel.add(chbLimit);

        JPanel optionPanel = new JPanel();
        optionPanel.setLayout(new FlowLayout(FlowLayout.LEADING));
        optionPanel.add(betterPricePanel);
        optionPanel.add(forceExecPanel);

        JPanel maxOrdersPanel = new JPanel();
        maxOrdersPanel.setBackground(new Color(200, 200, 240));
        maxOrdersPanel.add(chbMaxOrders);
        maxOrdersPanel.add(new JLabel("MaxAmount of Opened Orders:"));
        maxOrdersPanel.add(maxOrdersSpinner);
        chbMaxOrders.setSelected(false);
        maxOrdersSpinner.setEnabled(false);

        JPanel leveragePanel = new JPanel();
        leveragePanel.setBackground(Color.WHITE);
        leveragePanel.add(chbLeverage);
        leveragePanel.add(new JLabel("MaxUse of Leverage in % :"));
        leveragePanel.add(leverageSpinner);
        chbLeverage.setSelected(false);
        leverageSpinner.setEnabled(false);

        JPanel marginPanel = new JPanel();
        marginPanel.setLayout(new FlowLayout(FlowLayout.LEADING));
        marginPanel.add(maxOrdersPanel);
        marginPanel.add(leveragePanel);

        JPanel advancedSPanel = new JPanel();
        advancedSPanel.setLayout(new FlowLayout(FlowLayout.LEADING));
        advancedSPanel.add(chbMetaTraderApprove);
        advancedSPanel.add(btnAdvancedSettings);

        //JPanel buttonPanel = new JPanel(new GridLayout(1, 1, 5, 5));
        JPanel buttonPanel = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        // Radio Buttons
        c.weightx = 0.5;
        c.gridx = 0;
        c.gridy = 0;
        buttonPanel.add(radioBtPanel, c);
        //emptyLabel
        c.weightx = 1;
        c.gridx = 1;
        c.gridy = 0;
        buttonPanel.add(new JLabel(""), c);
        //emptyLabel
        c.weightx = 1;
        c.gridx = 2;
        c.gridy = 0;
        buttonPanel.add(new JLabel(""), c);

        // Spinner for Better Pricer 
        c.weightx = 0.5;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridx = 0;
        c.gridy = 1;
        buttonPanel.add(optionPanel, c);
        // checkbox for Limit orders 
        //c.weightx = 0.4;
        // c.fill = GridBagConstraints.HORIZONTAL;
        //c.gridx = 1;
        //c.gridy = 1;        
        //buttonPanel.add(chbLimit, c);
        chbLimit.setSelected(false);

        // checkbox for MetaTrader approve
        c.weightx = 0.5;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridx = 0;
        c.gridy = 2;
        buttonPanel.add(advancedSPanel, c);
        chbMetaTraderApprove.setSelected(false);
        // checkbox for MetaTrader approve

        // Use of Leverage and max Orders Amount
        c.weightx = 0.5;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridx = 0;
        c.gridy = 3;
        buttonPanel.add(marginPanel, c);

        translatorPane.add(buttonPanel, BorderLayout.PAGE_START);
        translatorPane.add(container, BorderLayout.CENTER);
        buttonPanel.setVisible(true);
        translatorPane.repaint();
        loadPreviousMTConnection();
        readMetaTraderLog();
    }

    class TranslatorTable extends JTable {

        private TableCellRenderer renderer;

        public TranslatorTable() {
            super(new TranslatorTableModel());
            setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
            setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            setRowSelectionAllowed(true);
            getTableHeader().setReorderingAllowed(false);

            renderer = new DefaultTableCellRenderer() {
                public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                    super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                    setHorizontalAlignment(SwingConstants.CENTER);
                    Color lightBlue = new Color(200, 200, 240);
                    try {
                        if (row % 2 == 0 && !isCellSelected(row, column)) {
                            setBackground(lightBlue);
                        } else if (isCellSelected(row, column)) {
                            setBackground(Color.LIGHT_GRAY);
                        } else {
                            setBackground(Color.WHITE);
                        }
                    } catch (ClassCastException e) {
                        e.printStackTrace();
                    }
                    return this;
                }
            };

            TableColumn column = columnModel.getColumn(0);
            //column.setCellEditor(new ComboBoxEditor(Instrument.values(), this));
            column.setMinWidth(60);
            column.setMaxWidth(60);

            column = columnModel.getColumn(1);
            //column.setCellEditor(new ComboBoxEditor(Condition.values(), this));
            column.setMinWidth(50);
            column.setMaxWidth(50);

            column = columnModel.getColumn(2);
            //column.setCellEditor(new SpinnerEditor());
            column.setMinWidth(70);
            column.setMaxWidth(70);

            column = columnModel.getColumn(3);
            //column.setCellEditor(new ComboBoxEditor(Notification.values(), this));
            column.setMinWidth(60);
            column.setMaxWidth(60);

            column = columnModel.getColumn(4);
            //column.setCellEditor(new ComboBoxEditor(new Status[] { Status.INACTIVE, Status.ACTIVE }, this));
            column.setMinWidth(50);
            column.setMaxWidth(50);

            column = columnModel.getColumn(5);
            //column.setCellEditor(new ComboBoxEditor(new Status[] { Status.INACTIVE, Status.ACTIVE }, this));
            column.setMinWidth(70);
            column.setMaxWidth(70);

            column = columnModel.getColumn(6);
            //column.setCellEditor(new ComboBoxEditor(new Status[] { Status.INACTIVE, Status.ACTIVE }, this));
            column.setMinWidth(70);
            column.setMaxWidth(70);

            column = columnModel.getColumn(7);
            column.setMinWidth(70);
            column.setMaxWidth(70);

            column = columnModel.getColumn(8);
            column.setMinWidth(110);
            column.setMaxWidth(110);

            column = columnModel.getColumn(9);
            column.setMinWidth(60);
            column.setMaxWidth(60);
        }

        public Dimension getPreferredScrollableViewportSize() {
            return new Dimension(getPreferredSize().width, getRowHeight() * 10);

        }

        public TableCellRenderer getCellRenderer(int row, int column) {
            return renderer;
        }

        public void stopCellEditing() {
            CellEditor cellEditor = getCellEditor();
            if (cellEditor != null) {
                cellEditor.stopCellEditing();
            }
        }

    }

    class TranslatorTableModel extends AbstractTableModel {

        private List<Order> orderList = new ArrayList<Order>();

        private String[] columns = {"Time", "Type", "Instrument", "Price", "Amount", "StopLoss", "TakeProfit", "OrderID", "JForexID", "Status"};

        private DateFormat df = new SimpleDateFormat("HH:mm:ss");

        public TranslatorTableModel() {
            df.setTimeZone(TimeZone.getTimeZone("GMT"));
        }

        public int getRowCount() {
            return orderList.size();
        }

        public int getColumnCount() {
            return columns.length;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            Order order = orderList.get(rowIndex);
            switch (columnIndex) {
                case 0:
                    return order.getTime();
                case 1:
                    return order.getType();
                case 2:
                    return order.getInstrument();
                case 3:
                    return order.getPrice();
                case 4:
                    return order.getAmount();
                case 5:
                    return order.getStopLossPrice();
                case 6:
                    return order.getTakeProfitPrice();
                case 7:
                    return order.getOrderMetaTraderID();
                case 8:
                    return order.getOrderJForexID();
                case 9:
                    return order.getStatus();
                default:
                    throw new IllegalArgumentException("Column " + columnIndex + " is undefined!");
            }
        }

        public String getColumnName(int columnIndex) {
            return columns[columnIndex];
        }

        public List<Order> getOrderList() {
            return orderList;
        }

        public void addOrder(Order order) {
            orderList.add(order);
            fireTableRowsInserted(orderList.size() - 1, orderList.size() - 1);
        }

        public void deleteOrder(int index) {
            orderList.remove(index);
            fireTableRowsDeleted(index, index);
        }

        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }

        public void setValueAt(Object value, int rowIndex, int columnIndex) {
            Order order = orderList.get(rowIndex);
            if (order != null) {
                switch (columnIndex) {
                    case 0:
                        order.setTime((String) value);
                        break;
                    case 1:
                        order.setType((String) value);
                        break;
                    case 2:
                        order.setInstrument((Instrument) value);
                        break;
                    case 3:
                        order.setPrice((Double) value);
                        break;
                    case 4:
                        order.setAmount((Double) value);
                        break;
                    case 5:
                        order.setStopLoss((Double) value);
                        break;
                    case 6:
                        order.setTakeProfit((Double) value);
                        break;
                    case 7:
                        order.setOrderMetaTraderID((String) value);
                        break;
                    case 8:
                        order.setOrderJForexID((String) value);
                        break;
                    case 9:
                        order.setStatus((String) value);
                        break;
                    default:
                        throw new IllegalArgumentException("Column " + columnIndex + " is not editable!");
                }
            }
            fireTableRowsUpdated(rowIndex, rowIndex);
        }
    }

    class ComboBoxEditor extends AbstractCellEditor implements TableCellEditor {

        private JComboBox comboBox;

        public ComboBoxEditor(Object[] options, TranslatorTable translatorTable) {
            comboBox = new JComboBox(options);
            final TranslatorTable table = translatorTable;
            comboBox.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    table.stopCellEditing();
                }
            });
        }

        public boolean isCellEditable(EventObject anEvent) {
            if (anEvent instanceof MouseEvent) {
                return ((MouseEvent) anEvent).getClickCount() >= 2;
            }
            return true;
        }

        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            return comboBox;
        }

        public Object getCellEditorValue() {
            return comboBox.getSelectedItem();
        }

    }

    class SpinnerEditor extends AbstractCellEditor implements TableCellEditor {

        private JSpinner usdSpinner;

        private JSpinner jpySpinner;

        private boolean jpyMode;

        public SpinnerEditor() {
            usdSpinner = new JSpinner(new SpinnerNumberModel(0.0001d, 0.00005d, 99.99995d, 0.00005d));
            usdSpinner.setEditor(new JSpinner.NumberEditor(usdSpinner, "#0.00000"));
            jpySpinner = new JSpinner(new SpinnerNumberModel(0.01d, 0.005d, 999.995d, 0.005d));
            jpySpinner.setEditor(new JSpinner.NumberEditor(jpySpinner, "##0.000"));
        }

        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            TranslatorTableModel tableModel = (TranslatorTableModel) table.getModel();
            Order order = tableModel.getOrderList().get(row);
            if (Currency.getInstance("JPY").equals(order.getInstrument().getSecondaryCurrency())) {
                jpyMode = true;
                jpySpinner.setValue(order.getPrice());
                return jpySpinner;
            } else {
                jpyMode = false;
                usdSpinner.setValue(order.getPrice());
                return usdSpinner;
            }
        }

        public boolean isCellEditable(EventObject anEvent) {
            if (anEvent instanceof MouseEvent) {
                return ((MouseEvent) anEvent).getClickCount() >= 2;
            }
            return true;
        }

        public Object getCellEditorValue() {
            if (jpyMode) {
                return BigDecimal.valueOf((Double) jpySpinner.getValue()).setScale(3, RoundingMode.HALF_EVEN);
            } else {
                return BigDecimal.valueOf((Double) usdSpinner.getValue()).setScale(5, RoundingMode.HALF_EVEN);
            }
        }
    }

    class Operation {
        public String orderLabel = "";
        public double stopLoss = 0;
        public double takeProfit = 0;

        public Operation(String orderLabel, double stopLoss, double takeProfit) {
            this.orderLabel = orderLabel;
            this.stopLoss = stopLoss;
            this.takeProfit = takeProfit;
        }
    }

    // Order Object
    class Order {

        // order time
        private String time;
        // sell or buy, sell stop, sell limit, buy limit, buy stop, market sell or buy
        private String type;
        private Instrument instrument;
        private double price;
        private double amount;
        private double takeProfitPrice;
        private double stopLossPrice;
        // MetaTrader Order Id, if order accepted and opened by MetaTrader
        private String orderMetaTraderID = "";
        // JForex Order ID
        private String orderJForexID = "";
        // Status Fill, Cancel
        private String status = "";

        public Order(Instrument instrument, String time, double price, String type, double amount, double takeProfitPrice, double stopLossPrice) {
            this.instrument = instrument;
            this.time = time;
            this.price = price;
            this.type = type;
            this.amount = amount;
            this.takeProfitPrice = takeProfitPrice;
            this.stopLossPrice = stopLossPrice;
        }

        public Instrument getInstrument() {
            return instrument;
        }

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

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public void setStopLoss(double stopLossPrice) {
            this.stopLossPrice = stopLossPrice;
        }

        public void setTakeProfit(double takeProfitPrice) {
            this.takeProfitPrice = takeProfitPrice;
        }

        public double getTakeProfitPrice() {
            return takeProfitPrice;
        }

        public double getStopLossPrice() {
            return stopLossPrice;
        }

        public double getPrice() {
            return price;
        }

        public void setPrice(double price) {
            this.price = price;
        }

        public String getTime() {
            return time;
        }

        public void setAmount(double amount) {
            this.amount = amount;
        }

        public void setTime(String time) {
            this.time = time;
        }

        public double getAmount() {
            return amount;
        }

        public String toString() {
            return "Alert on " + instrument + " " + time + " " + price;
        }

        public String getOrderMetaTraderID() {
            return orderMetaTraderID;
        }

        public void setOrderMetaTraderID(String id) {
            orderMetaTraderID = id;
        }

        public String getOrderJForexID() {
            return orderJForexID;
        }

        public void setOrderJForexID(String id) {
            orderJForexID = id;
        }

        public String getStatus() {
            return status;
        }

        public void setStatus(String status) {
            this.status = status;
        }

    }

    enum Condition {

        BID_LESS("BID <", true),
        BID_GREATER("BID >", true),
        ASK_LESS("ASK <", false),
        ASK_GREATER("ASK >", false);

        private String name;

        private boolean bidCondition;

        Condition(String name, boolean bidCondition) {
            this.name = name;
            this.bidCondition = bidCondition;
        }

        public String toString() {
            return name;
        }

        public boolean isBidCondition() {
            return bidCondition;
        }

    }

    enum Notification {

        POPUP("Pop-up"),
        BEEP("Alarm");

        private String name;

        Notification(String name) {
            this.name = name;
        }

        public String toString() {
            return name;
        }

    }

    enum Status {

        INACTIVE("Inactive"),
        ACTIVE("Active"),
        COMPLETED("Completed");

        private String name;

        Status(String name) {
            this.name = name;
        }

        public String toString() {
            return name;
        }
    }

    protected String getLabel() {
        String label;
        String time = "" + getCurrentTime();
        //time = time.substring(4, time.length() - 1);
        label = "IBridge" + time + generateRandom(10000) + generateRandom(10000);
        return label;
    }

    private String getCurrentTime() {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
        return sdf.format(cal.getTime());
    }

    //Need in cases if pipsValues less than in JForex
    private double getRoundedPrice(Instrument instrument, double price) {
        if (price != 0) {
            String strPrice = "" + price;
            if (strPrice.contains(".")) {
                // lets calculate the PipsValue
                int length = strPrice.substring(strPrice.lastIndexOf(".") + 1, strPrice.length()).length();
                if (instrument.getPipScale() < length) {
                    int lastNumber = Integer.parseInt(strPrice.substring(strPrice.length() - 1, strPrice.length()));
                    if (lastNumber > instrument.getPipScale()) {
                        double priceB = price;
                        priceB = Math.ceil(priceB * Math.pow(10, length - 1));
                        priceB = priceB / Math.pow(10, length - 1);
                        return priceB;
                    } else {
                        double priceB = price;
                        priceB = Math.floor(priceB * Math.pow(10, length - 1));
                        priceB = priceB / Math.pow(10, length - 1);
                        return priceB;
                    }
                }
            }
        }
        return price;
    }

    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;
    }

    // Sets the order ID from MetaTrader to the order
    private synchronized void setMetaTraderId(String orderID, Order order) {
        if (orderID != null && orderID.length() > 2) {
            orderID = orderID.substring(1, orderID.length());
            order.setOrderMetaTraderID(orderID);
        }
    }

    // Sets the order ID from MetaTrader to the tables
    private synchronized void setMetaTraderId(String orderID) {
        if (orderID != null && orderID.length() > 2) {
            logEvent("Setting OrderID " + orderID);
            orderID = orderID.substring(1, orderID.length());
            int lastMetaTraderRow = ((TranslatorTableModel) translatorTable.getModel()).getOrderList().size() - 1;
            int lastJForexRow = ((TranslatorTableModel) jforexTable.getModel()).getOrderList().size() - 1;
            if (lastMetaTraderRow > -1) {
                Order order = ((TranslatorTableModel) translatorTable.getModel()).getOrderList().get(lastMetaTraderRow);
                if (order.getOrderMetaTraderID().length() == 0) {
                    order.setOrderMetaTraderID(orderID);
                }
            }
            if (lastJForexRow > -1) {
                Order order = ((TranslatorTableModel) jforexTable.getModel()).getOrderList().get(lastJForexRow);
                if (order.getOrderMetaTraderID().length() == 0) {
                    order.setOrderMetaTraderID(orderID);
                }
            }
        }
    }

    private Order getMetaTraderOrder(TranslatorTable table, String orderID) {
        for (int i = 0; i < ((TranslatorTableModel) table.getModel()).getOrderList().size(); i++) {
            Order order = ((TranslatorTableModel) table.getModel()).getOrderList().get(i);
            if (order.getOrderMetaTraderID().equals(orderID)) {
                return order;
            }
        }
        return null;
    }

    private Order getJForexOrder(TranslatorTable table, String orderID) {
        for (int i = 0; i < ((TranslatorTableModel) table.getModel()).getOrderList().size(); i++) {
            Order order = ((TranslatorTableModel) table.getModel()).getOrderList().get(i);
            if (order.getOrderJForexID().equals(orderID)) {
                return order;
            }
        }
        return null;
    }

    // Modife order if in MetaTrader the order was changed
    private void modifyOrder(String orderID, double price, double stopLoss, double takeProfit) {
        if (orderID != null && orderID.length() > 2) {
            orderID = orderID.substring(1, orderID.length());
            // change the MetaTrader table
            Order order = getMetaTraderOrder(translatorTable, orderID);
            if (order != null) {
                order.setPrice(price);
                order.setStopLoss(stopLoss);
                order.setTakeProfit(takeProfit);
            }
            // change the JForex table
            order = getMetaTraderOrder(jforexTable, orderID);
            if (order != null) {
                logEvent("Order was Modified " + orderID + " Price: " + price + " stopLoss: " + stopLoss + " takeProfit " + takeProfit);
                price = getRoundedPrice(order.getInstrument(), price);
                takeProfit = getRoundedPrice(order.getInstrument(), takeProfit);
                stopLoss = getRoundedPrice(order.getInstrument(), stopLoss);
                order.setPrice(price);
                order.setStopLoss(stopLoss);
                order.setTakeProfit(takeProfit);
                DoChangeOrderTask task = new DoChangeOrderTask(order.getOrderJForexID(), price, stopLoss, takeProfit);
                context.executeTask(task);
            }
        }
    }

    // Modife order if in MetaTrader the order was changed
    private void modifyOrder(String orderID, double stopLoss, double takeProfit) {
        if (orderID != null && orderID.length() > 2) {
            orderID = orderID.substring(1, orderID.length());
            // change the MetaTrader table
            Order order = getMetaTraderOrder(translatorTable, orderID);
            if (order != null) {
                order.setStopLoss(stopLoss);
                order.setTakeProfit(takeProfit);
            }

            // change the JForex table
            order = getMetaTraderOrder(jforexTable, orderID);
            if (order != null) {
                order.setStopLoss(stopLoss);
                order.setTakeProfit(takeProfit);
                if (order.getStatus().length() != 0) {
                    logEvent("Order was Modified " + orderID + " stopLoss: " + stopLoss + " takeProfit " + takeProfit);
                    takeProfit = getRoundedPrice(order.getInstrument(), takeProfit);
                    stopLoss = getRoundedPrice(order.getInstrument(), stopLoss);
                    order.setStopLoss(stopLoss);
                    order.setTakeProfit(takeProfit);
                    DoChangeInstantOrderTask task = new DoChangeInstantOrderTask(order.getOrderJForexID(), stopLoss, takeProfit);
                    context.executeTask(task);
                } else {
                    takeProfit = getRoundedPrice(order.getInstrument(), takeProfit);
                    stopLoss = getRoundedPrice(order.getInstrument(), stopLoss);
                    order.setStopLoss(stopLoss);
                    order.setTakeProfit(takeProfit);
                    logEvent("Order Modification is on Delay Operation " + orderID + " stopLoss: " + stopLoss + " takeProfit " + takeProfit);
                    listOperations.add(new Operation(order.getOrderJForexID(), stopLoss, takeProfit));
                }
            }
        }
    }


    private class DoChangeOrderTask implements Callable<Object> {
        String forexID = "";
        double price = 0;
        double stopLoss = 0;
        double takeProfit = 0;

        public DoChangeOrderTask(String forexID, double price, double stopLoss, double takeProfit) {
            this.forexID = forexID;
            this.price = price;
            this.stopLoss = stopLoss;
            this.takeProfit = takeProfit;
        }

        public Object call() {
            try {
                IOrder dukaOrder = engine.getOrder(forexID);
                dukaOrder.setStopLossPrice(stopLoss);
                dukaOrder.setTakeProfitPrice(takeProfit);
                dukaOrder.setOpenPrice(price);
            } catch (JFException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    private class DoChangeInstantOrderTask implements Callable<Object> {
        String forexID = "";
        double stopLoss = 0;
        double takeProfit = 0;

        public DoChangeInstantOrderTask(String forexID, double stopLoss, double takeProfit) {
            this.forexID = forexID;
            this.stopLoss = stopLoss;
            this.takeProfit = takeProfit;
        }

        public Object call() {
            try {
                IOrder dukaOrder = engine.getOrder(forexID);
                dukaOrder.setStopLossPrice(stopLoss);
                dukaOrder.setTakeProfitPrice(takeProfit);
            } catch (JFException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    // Order Delete
    private void deleteOrder(String orderID) {
        if (orderID != null && orderID.length() > 2) {
            orderID = orderID.substring(1, orderID.length());
            // delete from the MetaTrader table            
            for (int i = 0; i < ((TranslatorTableModel) translatorTable.getModel()).getOrderList().size(); i++) {
                Order order = ((TranslatorTableModel) translatorTable.getModel()).getOrderList().get(i);
                if (order.getOrderMetaTraderID().equals(orderID)) {
                    ((TranslatorTableModel) translatorTable.getModel()).deleteOrder(i);
                    break;
                }
            }
            String jforexID = "";
            // delete from the JForex table
            for (int i = 0; i < ((TranslatorTableModel) jforexTable.getModel()).getOrderList().size(); i++) {
                Order order = ((TranslatorTableModel) jforexTable.getModel()).getOrderList().get(i);
                if (order.getOrderMetaTraderID().equals(orderID)) {
                    jforexID = order.getOrderJForexID();
                    ((TranslatorTableModel) jforexTable.getModel()).deleteOrder(i);
                    break;
                }
            }
            if (jforexID.length() > 0) {
                DoDeleteOrderTask task = new DoDeleteOrderTask(jforexID, 0, false);
                logEvent("Order was Closed " + orderID);
                context.executeTask(task);
            }
        }
    }

    private class DoDeleteOrderTask implements Callable<Object> {
        String forexID = "";
        double amount = -1;
        boolean isPartial = false;

        public DoDeleteOrderTask(String forexID, double amount, boolean isPartial) {
            this.forexID = forexID;
            this.amount = amount;
            this.isPartial = isPartial;
        }

        public Object call() {
            try {
                IOrder dukaOrder = engine.getOrder(forexID);

                if (amount > -1) {
                    if (!isPartial) {
                        if (chbLimit.isSelected()) {
//                            double price = history.getLastTick(dukaOrder.getInstrument()).getBid();
//                           if (dukaOrder.getOrderCommand().toString().contains("SELL") || dukaOrder.getOrderCommand().toString().contains("OFFER")) {
//                                price = history.getLastTick(dukaOrder.getInstrument()).getAsk();
//                            }
//                            dukaOrder.setStopLossPrice(price);
//                            dukaOrder.setTakeProfitPrice(price);
                            double price = history.getLastTick(dukaOrder.getInstrument()).getBid();
                            if (dukaOrder.getOrderCommand().toString().contains("SELL") || dukaOrder.getOrderCommand().toString().contains("OFFER")) {
                                dukaOrder.setStopLossPrice(price - 200 * orderCurrent.getInstrument().getPipValue());
                            } else {
                                dukaOrder.setTakeProfitPrice(price - 200 * orderCurrent.getInstrument().getPipValue());
                            }
                        } else {
                            dukaOrder.close();
                        }
                    } else {
                        dukaOrder.close(amount);
                    }
                } else {
                    if (chbLimit.isSelected()) {
                        double price = history.getLastTick(dukaOrder.getInstrument()).getBid();
                        if (dukaOrder.getOrderCommand().toString().contains("SELL") || dukaOrder.getOrderCommand().toString().contains("OFFER")) {
                            dukaOrder.setStopLossPrice(price - 200 * orderCurrent.getInstrument().getPipValue());
                        } else {
                            dukaOrder.setTakeProfitPrice(price - 200 * orderCurrent.getInstrument().getPipValue());
                        }
                    } else {
                        dukaOrder.close();
                    }
                }
            } catch (JFException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    // Order Close
    private void closeOrder(String orderID, double amount) {
        if (orderID != null && orderID.length() > 2) {
            String status = "Closed";
            boolean isPartial = false;
            orderID = orderID.substring(1, orderID.length());
            // delete from the MetaTrader table            
            for (int i = 0; i < ((TranslatorTableModel) translatorTable.getModel()).getOrderList().size(); i++) {
                Order order = ((TranslatorTableModel) translatorTable.getModel()).getOrderList().get(i);
                if (order.getOrderMetaTraderID().equals(orderID)) {
                    if (order.getAmount() > amount) {
                        status = "Partial Close";
                        isPartial = true;
                    }
                    order.setAmount(order.getAmount() - amount);
                    order.setStatus(status);
                    break;
                }

            }
            String jforexID = "";
            // delete from the JForex table
            for (int i = 0; i < ((TranslatorTableModel) jforexTable.getModel()).getOrderList().size(); i++) {
                Order order = ((TranslatorTableModel) jforexTable.getModel()).getOrderList().get(i);
                if (order.getOrderMetaTraderID().equals(orderID)) {
                    jforexID = order.getOrderJForexID();
                    if (order.getAmount() > amount) {
                        status = "Partial Close";
                        isPartial = true;
                    }
                    order.setAmount(order.getAmount() - amount);
                    order.setStatus(status);
                    break;
                }
            }
            if (jforexID.length() > 0) {
                DoDeleteOrderTask task = new DoDeleteOrderTask(jforexID, amount, isPartial);
                context.executeTask(task);
            }
        }
    }

    private boolean isBetterPrice(Order orderCurrent) {
        try {
            if (orderCurrent.getType().contains("buy")) {
                double price = history.getLastTick(orderCurrent.getInstrument()).getBid();
                if ((price + ((Double) spinner.getValue()) * orderCurrent.getInstrument().getPipValue()) <= orderCurrent.getPrice()) {
                    return true;
                }
            }
            if (orderCurrent.getType().contains("sell")) {
                double price = history.getLastTick(orderCurrent.getInstrument()).getAsk();
                if ((price - ((Double) spinner.getValue()) * orderCurrent.getInstrument().getPipValue()) >= orderCurrent.getPrice()) {
                    return true;
                }
            }
        } catch (JFException e) {
            e.printStackTrace();
        }
        return false;
    }

    private void setBetterPrice(Order orderCurrent) {
        try {
            if (orderCurrent.getType().contains("buy")) {
                double price = history.getLastTick(orderCurrent.getInstrument()).getBid();
                if ((price + ((Double) spinner.getValue()) * orderCurrent.getInstrument().getPipValue()) <= orderCurrent.getPrice()) {
                    orderCurrent.setPrice(price);
                }
            }
            if (orderCurrent.getType().contains("sell")) {
                double price = history.getLastTick(orderCurrent.getInstrument()).getAsk();
                if ((price - ((Double) spinner.getValue()) * orderCurrent.getInstrument().getPipValue()) >= orderCurrent.getPrice()) {
                    orderCurrent.setPrice(price);
                }
            }
        } catch (JFException e) {
            e.printStackTrace();
        }
    }

    private synchronized void setAutomaticLogFile() {
        // Check if need to go to the new file
        Calendar cal = Calendar.getInstance();
        int day = cal.get(Calendar.DATE);
        int month = cal.get(Calendar.MONTH) + 1;
        int year = cal.get(Calendar.YEAR);
        String monthS = "" + month;
        String dayS = "" + day;
        if (month < 10) {
            monthS = "0" + monthS;
        }
        if (day < 10) {
            dayS = "0" + dayS;
        }
        String currentDate = "" + year + monthS + dayS;
        String currentLog = logFile.getAbsolutePath().substring(logFile.getAbsolutePath().length() - 12, logFile.getAbsolutePath().length() - 4);

        if (dayNumber == 0) {
            dayNumber = day;
        } else if (!currentDate.equals(currentLog)) {
            logEvent("New Log File is Set " + currentDate);
            String newPath = logFile.getAbsolutePath().replaceFirst(currentLog, currentDate);
            logFile = new File(newPath);
            lastRecordTime = 0;
            filePreviousSize = 0;
        }
    }

    private void logEvent(String text) {
        try {
            BufferedWriter bw = new BufferedWriter(new FileWriter(bridgeLog, true));
            DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            Date date = new java.util.Date();
            String datetime = df.format(date);
            bw.write(datetime + "  " + text);
            bw.newLine();
            bw.flush();
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String getInstrumentWithoutPrefix(String value) {
        if (value.length() > 6) {
            value = value.substring(0, 6);
        }
        try {
            Instrument.valueOf(value);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            value = null;
        }
        return value;
    }

    // Order Rename - ussually due to partial Close
    private void renameOrder(String orderID, String newOrderID) {
        if (orderID != null && orderID.length() > 2) {
            orderID = orderID.substring(1, orderID.length());
            newOrderID = newOrderID.substring(1, newOrderID.length());
            // rename from the MetaTrader table            
            for (int i = 0; i < ((TranslatorTableModel) translatorTable.getModel()).getOrderList().size(); i++) {
                Order order = ((TranslatorTableModel) translatorTable.getModel()).getOrderList().get(i);
                if (order.getOrderMetaTraderID().equals(orderID)) {
                    order.setOrderMetaTraderID(newOrderID);
                    break;
                }
            }

            // rename from the JForex table
            for (int i = 0; i < ((TranslatorTableModel) jforexTable.getModel()).getOrderList().size(); i++) {
                Order order = ((TranslatorTableModel) jforexTable.getModel()).getOrderList().get(i);
                if (order.getOrderMetaTraderID().equals(orderID)) {
                    order.setOrderMetaTraderID(newOrderID);
                    break;
                }
            }
        }
    }

    //
    private void processOperation(IOrder order) {
        for (int i = 0; i < listOperations.size(); i++) {
            Operation operation = listOperations.get(i);
            if (operation.orderLabel.equals(order.getLabel())) {
                logEvent("Order was Modified with Operation " + order.getLabel() + " stopLoss: " + operation.stopLoss + " takeProfit " + operation.takeProfit);
                DoChangeInstantOrderTask task = new DoChangeInstantOrderTask(order.getLabel(), operation.stopLoss, operation.takeProfit);
                context.executeTask(task);
                listOperations.remove(i);
            }
        }
    }

    // need for lines which have the same time
    private boolean isNotPrevLine(String line) {
        for (int i = 0; i < listRepeatLines.size(); i++) {
            String prevLine = listRepeatLines.get(i);
            if (prevLine.equals(line)) {
                return false;
            }
        }
        return true;
    }

    private void addRepeatableData(String line) {
        if (isNotPrevLine(line)) {
            listRepeatLines.add(line);
        }
    }

    private void clearRepeatableData() {
        listRepeatLines.clear();
    }

    // check for the use of leverage
    private boolean isUseofLeverageOK() {
        if (!chbLeverage.isSelected()) {
            return true;
        } else {
            int leverage = (Integer) leverageSpinner.getValue();
            if (account.getUseOfLeverage() >= leverage) {
                logEvent("Order was rejected by option use of Leverage: " + leverageSpinner.getValue());
                return false;
            }
        }
        return true;
    }

    // getCurrent time
    private long getCurrTime(Date date) {
        return (date.getTime() + tz.getRawOffset());
    }

    void copy(File src, File dst) throws IOException {
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dst, true);

        // Transfer bytes from in to out
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();
    }

    // check for max amount of orders
    private boolean isMaxOrdersOK() {
        try {
            if (!chbMaxOrders.isSelected()) {
                return true;
            } else {
                List<IOrder> orderList = engine.getOrders();
                if ((orderList.size()) >= (Integer) maxOrdersSpinner.getValue()) {
                    logEvent("Order was rejected by option use max orders amount: " + maxOrdersSpinner.getValue());
                    return false;
                }
            }
        } catch (JFException e) {
            e.printStackTrace();
        }
        return true;
    }

    private double isMinimumLotAmount(double lotAmount) {
        if (chbCheckMaxLotAmount.isSelected()) {
            try {
                double maxLotAmount = (Double.parseDouble(txtMaxLotAmount.getText()));
                if (maxLotAmount < lotAmount) {
                    lotAmount = maxLotAmount;
                }
            } catch (Exception e) {
                logEvent("max lot amount parsing is wrong");
                e.printStackTrace();
            }
        }
        if (isMinLotAmount && lotAmount < 0.001) {
            logEvent("MinLotAmount is used for amount " + lotAmount);
            lotAmount = 0.001;
        }

        return lotAmount;
    }

    private void createMTRestoreFile() {
        // create Restoration file
        try {
            String currentLogPath = logFile.getAbsolutePath().substring(0, logFile.getAbsolutePath().length() - 12);
            restorationLog = new File(currentLogPath + restorationsLog);
            if (!restorationLog.exists()) {
                restorationLog.createNewFile();
                logEvent("Restoration File is created");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private void saveMTConnection() {
        try {
            //System.out.println(" save ");
            BufferedWriter bw = new BufferedWriter(new FileWriter(restorationLog));
            // rename from the JForex table
            for (int i = 0; i < ((TranslatorTableModel) jforexTable.getModel()).getOrderList().size(); i++) {
                Order order = ((TranslatorTableModel) jforexTable.getModel()).getOrderList().get(i);
                if (!order.getStatus().equals("CLOSED") && !order.getStatus().equals("CANCELED") && order.getOrderMetaTraderID().length() > 1) {
                    bw.write(order.getOrderMetaTraderID() + " " + order.getOrderJForexID());
                    bw.newLine();
                }
            }
            bw.flush();
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private synchronized void loadPreviousMTConnection() {
        FileInputStream fis;
        BufferedInputStream bis;
        DataInputStream dis;
        try {
            if (restorationLog.exists()) {
                fis = new FileInputStream(restorationLog);
                //logEvent("Restoration procedure");
                String previousLine = "";
                String strLine = "";
                // Here BufferedInputStream is added for fast reading.
                bis = new BufferedInputStream(fis);
                dis = new DataInputStream(bis);
                // dis.available() returns 0 if the file does not have more lines.
                while (dis.available() != 0) {
                    strLine = dis.readLine();
                    String f[] = strLine.split(" ");
                    if (f != null && f.length > 1) {
                        final List<IOrder> orderList = engine.getOrders();
                        String ff = f[1].trim();
                        final TranslatorTableModel modelJF = (TranslatorTableModel) jforexTable.getModel();
                        for (IOrder order : orderList) {
                            //logEvent("Debug:: Restored Info " + f[0] + " vs " + f[1]);
                            //logEvent("Is those order is the same :: "  + order.getLabel() + " " + ff);
                            //System.out.println("" + "Is those order is the same :: "  + order.getLabel() + " " + ff);
                            //System.out.println(" " + order.getState() + " " + order.getId());
                            //String resultCheck = order.getLabel().trim();

                            if (order != null && order.getLabel() != null && order.getLabel().equals(ff)) {
                                //logEvent("Debug:: order to restore ");
                                //logEvent("Debug:: instrument " + order.getInstrument());
                                //logEvent("Debug:: price " +order.getOpenPrice());
                                //logEvent("Debug:: command " + order.getOrderCommand());
                                //logEvent("Debug:: amount " + order.getAmount());
                                //logEvent("Debug:: TP " +order.getTakeProfitPrice());
                                //logEvent("Debug:: SL " +order.getStopLossPrice());
                                //logEvent("Debug:: State " + order.getState().name());

                                Order restoredOrder = new Order(order.getInstrument(), "Restored", order.getOpenPrice(), order.getOrderCommand() + "", order.getAmount(), order.getTakeProfitPrice(), order.getStopLossPrice());
                                // lets create records
                                restoredOrder.setOrderMetaTraderID(f[0]);
                                restoredOrder.setOrderJForexID(f[1]);
                                restoredOrder.setStatus(order.getState().name());
                                modelJF.addOrder(restoredOrder);
                                jforexTable.repaint();
                                //logEvent("Debug::  " + f[1] + "Restored Succesfully");
                                //TranslatorTableModel model = (TranslatorTableModel) translatorTable.getModel();
                                //model.addOrder(restoredOrder);
                            } else if (order.getLabel() == null) {
                                logEvent("Debug::  " + f[1] + "Restored Unsuccesfully !! " + order.getId());
                            } else {

                            }
                        }
                    }
                    // dispose all the resources after using them.
                }

                fis.close();
                bis.close();
                dis.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JFException e) {
            e.printStackTrace();
        }
    }

    private String getDurationDate() {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_DURATION);
        return sdf.format(cal.getTime());
    }

    private void initAdvancedSettings() {
        txtMaxLotAmount.setMinimumSize(new Dimension(140, 20));
        txtWorkDurationFrom.setSize(80, 20);
        txtWorkDurationTo.setSize(80, 20);
        txtMaxLotAmount.repaint();
        chbCheckMaxLotAmount.setSelected(false);
        chbCheckMaxLotAmount.setSelected(false);
        txtWorkDurationFrom.setEnabled(false);
        txtWorkDurationTo.setEnabled(false);
        txtMaxLotAmount.setEnabled(false);

        txtWorkDurationFrom.setText("" + getDurationDate());
        txtWorkDurationTo.setText("" + getDurationDate());
    }

    private boolean isInsideDuration() {
        if (chbCheckWorkDuration.isSelected()) {
            try {
                DateFormat formatter = new SimpleDateFormat(DATE_FORMAT_DURATION);
                Date dateFrom = formatter.parse(txtWorkDurationFrom.getText());
                Date dateTo = formatter.parse(txtWorkDurationTo.getText());
                Calendar cal = Calendar.getInstance();
                long current = getCurrTime(cal.getTime());
                //System.out.println("" + current);
                //System.out.println(getCurrTime(dateFrom) + " : " + getCurrTime(dateTo));
                if (current >= getCurrTime(dateFrom) && current < getCurrTime(dateTo)) {
                    //System.out.println(" true");
                    return true;
                } else {
                    //System.out.println(" false");
                    return false;
                }
            } catch (ParseException e) {
                e.printStackTrace();
                logEvent("Inside Duration Parse Error");
            }
        }
        //System.out.println(" treue 2");
        return true;
    }

    private void showAdvancedSettings() {
        final JDialog dlgAdvanced = new JDialog();
        dlgAdvanced.setSize(450, 200);
        dlgAdvanced.setTitle("MT4DukaBridge Advanced Settings");
        dlgAdvanced.setLocation(btnAdvancedSettings.getLocation());

        chbCheckMaxLotAmount.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (chbCheckMaxLotAmount.isSelected()) {
                    txtMaxLotAmount.setEnabled(true);
                    logEvent("Max Lot Amount is set");
                } else {
                    txtMaxLotAmount.setEnabled(false);
                    logEvent("Max Lot Amount is Unset");
                }
            }
        });

        chbCheckWorkDuration.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (chbCheckWorkDuration.isSelected()) {
                    txtWorkDurationFrom.setEnabled(true);
                    txtWorkDurationTo.setEnabled(true);
                } else {
                    txtWorkDurationFrom.setEnabled(false);
                    txtWorkDurationTo.setEnabled(false);
                }
            }
        });

        JButton btnOk = new JButton("Ok");
        JButton btnCancel = new JButton("Cancel");
        btnOk.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                dlgAdvanced.dispose();
            }
        });

        btnCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                dlgAdvanced.dispose();
            }
        });

        JPanel panel01 = new JPanel(new FlowLayout(FlowLayout.LEADING));
        panel01.add(new JLabel("Check for Max Order Amount, no More Than: "));
        panel01.add(chbCheckMaxLotAmount);

        JPanel panel02 = new JPanel(new FlowLayout(FlowLayout.LEADING));
        panel02.add(new JLabel("Set Bridge Work During the Following Time: "));
        panel02.add(chbCheckWorkDuration);
        //panel02.add(new JLabel("yyyy/MM/DD HH:mm"));

        JPanel panel03 = new JPanel(new FlowLayout(FlowLayout.LEADING));
        panel03.add(new JLabel("                         "));
        panel03.add(new JLabel("From : "));
        //panel03.add(txtWorkDurationFrom);

        JPanel panel04 = new JPanel(new FlowLayout(FlowLayout.LEADING));
        panel04.add(new JLabel("                         "));
        panel04.add(new JLabel("To :"));
        //panel04.add(txtWorkDurationTo);

        JPanel panel05 = new JPanel(new FlowLayout(FlowLayout.LEADING));
        panel05.add(new JLabel("                                "));
        panel05.add(btnOk);
        //panel05.add(btnCancel);

        JPanel buttonPanel = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 0;
        c.gridy = 0;
        buttonPanel.add(panel01, c);
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 1;
        c.gridy = 0;
        buttonPanel.add(txtMaxLotAmount, c);
        c.weightx = 0.5;
        c.gridx = 2;
        c.gridy = 0;
        buttonPanel.add(new JLabel("  "), c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 0;
        c.gridy = 1;
        buttonPanel.add(panel02, c);
        c.weightx = 0.5;
        c.gridx = 1;
        c.gridy = 1;
        buttonPanel.add(new JLabel("yyyy/MM/DD HH:mm"), c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 0;
        c.gridy = 2;
        buttonPanel.add(panel03, c);
        c.weightx = 0.5;
        c.gridx = 1;
        c.gridy = 2;
        buttonPanel.add(txtWorkDurationFrom, c);
        c.weightx = 0.5;
        c.gridx = 2;
        c.gridy = 2;
        buttonPanel.add(new JLabel("  "), c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 0;
        c.gridy = 3;
        buttonPanel.add(panel04, c);
        c.weightx = 0.5;
        c.gridx = 1;
        c.gridy = 3;
        buttonPanel.add(txtWorkDurationTo, c);
        c.weightx = 0.5;
        c.gridx = 2;
        c.gridy = 3;
        buttonPanel.add(new JLabel("  "), c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0.5;
        c.gridx = 0;
        c.gridy = 4;
        buttonPanel.add(panel05, c);

        dlgAdvanced.add(buttonPanel);
        dlgAdvanced.setVisible(true);
    }
}