package eu.gity.jmeter.serveremulator;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.io.File;

import java.io.IOException;
import java.net.*;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.ToolTipManager;
import javax.swing.JSpinner.DefaultEditor;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;


import org.apache.jmeter.config.gui.AbstractConfigGui;
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.gui.action.ActionRouter;
import org.apache.jmeter.gui.action.ExitCommand;
import org.apache.jmeter.samplers.Clearable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestStateListener;
import org.apache.jmeter.util.JMeterUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import static eu.gity.jmeter.serveremulator.properties.strings.ServerEmulatorPropertiesStrings.*;


/**
 * This GUI class besides providing interface for setting parameters serves also as main control class of this plug-in.
 * It controls tasks for managing the FTP and HTTP(S) servers which are implemented in the ServerEmulatorCore class.
 *
 * @author Gity a.s.
 */

public class ServerEmulatorGui extends AbstractConfigGui implements Clearable, ActionListener, ChangeListener {

    private static final long serialVersionUID = 240L;
    private static final Logger log = LoggerFactory.getLogger(ServerEmulatorGui.class);
    private final JButton startHTTPServer = new JButton(JMeterUtils.getLocaleString(SERVER_EMULATOR_START_NOW));
    private final JButton stopHTTPServer = new JButton(JMeterUtils.getLocaleString(SERVER_EMULATOR_STOP_NOW));
    private final JButton httpServerStatus = new JButton(JMeterUtils.getLocaleString(SERVER_EMULATOR_DISPLAY_STATUS));
    private final JButton startFTPServer = new JButton(JMeterUtils.getLocaleString(SERVER_EMULATOR_START_NOW));
    private final JButton stopFTPServer = new JButton(JMeterUtils.getLocaleString(SERVER_EMULATOR_STOP_NOW));
    private final JButton ftpServerStatus = new JButton(JMeterUtils.getLocaleString(SERVER_EMULATOR_DISPLAY_STATUS));
    private JCheckBox enableSSLCB;
    private JTextField httpPortTF;
    private JTextArea infoTextArea;
    private JCheckBox singleMachineCB;
    private JCheckBox httpAutoStartCB;
    private JCheckBox ftpAutoStartCB;
    private JSpinner htmlSizeSpinner;
    private double htmlSize;
    private JTextField ipTFByte1;
    private JTextField ipTFByte2;
    private JTextField ipTFByte3;
    private JTextField ipTFByte4Start;
    private JTextField ipTFByte4End;
    private JTabbedPane tabbedPane;
    private JPanel advancedPanel;
    private JTextField startServersTF;
    private JTextField maxRequestWorkersTF;
    private JTextField threadsPerChildTF;
    private JTextField minSpareThreadsTF;
    private JTextField maxSpareThreadsTF;
    private JCheckBox enableAdvancedCB;
    private JButton defaultsBtn = new JButton(JMeterUtils.getLocaleString(SERVER_EMULATOR_RESET_TO_DEFAULTS));
    private ServerEmulatorCore serverEmulatorCore;
    private String jmeterHomeDir;
    private boolean nsConfigured;
    private String nsName = "";
    private JLabel listenCaptionLbl;
    private JLabel listenDevNameLbl;
    private boolean httpStartedBySE;
    private boolean ftpStartedBySE;

    //-------------------------------

    // COMMON VARIABLES

    private JButton showIPtoInterface;

    private JButton addIPtoInterface;

    private JButton deleteIPtoInterface;

    //Interface
    private JTextField commonInterface;

    //Mask

    private JTextField commonIPv4Mask;

    private JTextField commonIPv6Mask;

    //Common IPv4 field
    private JTextField commonIPbyte1;
    private JTextField commonIPbyte2;
    private JTextField commonIPbyte3;
    private JTextField commonIPbyte4;

    //Common IPv6 field
    private JTextField commonIPv6Hextet1;
    private JTextField commonIPv6Hextet2;
    private JTextField commonIPv6Hextet3;
    private JTextField commonIPv6Hextet4;
    private JTextField commonIPv6Hextet5;
    private JTextField commonIPv6Hextet6;
    private JTextField commonIPv6Hextet7;
    private JTextField commonIPv6Hextet8;

    // DNS VARIABLES

    // podmínka, která řeší v ActionListeners DNS, aby startstop nemazal původní konfiguraci


    private boolean DNSpodminka=true;

    private boolean DHCPpodminka=true;

    private boolean NTPpodminka=true;

    private boolean dnsStartedBySE;

    JCheckBox dnsSEC;
    private JButton dnsStatus;
    private JButton startDNS;
    private JButton stopDNS;

    private JButton restartDNS;

    private JTextField dnsPORT;

    //DNS IPv4 pole
    private JTextField dnsIPbyte1;
    private JTextField dnsIPbyte2;
    private JTextField dnsIPbyte3;
    private JTextField dnsIPbyte4;

    //DNS IPv6 pole
    private JTextField dnsIPv6Hextet1;
    private JTextField dnsIPv6Hextet2;
    private JTextField dnsIPv6Hextet3;
    private JTextField dnsIPv6Hextet4;
    private JTextField dnsIPv6Hextet5;
    private JTextField dnsIPv6Hextet6;
    private JTextField dnsIPv6Hextet7;
    private JTextField dnsIPv6Hextet8;


    //DHCP VARIABLES

    private JButton dhcpStatus;
    private JButton startDHCP;
    private JButton stopDHCP;

    private JButton displayUsedPorts;

    private JButton displayDHCPattachedIPs;

    private JTextField portsDHCP;

    private JButton addDHCPport;

    private JButton deleteDHCPport;

    private JButton restartDHCP;

    private JTextField dhcpIPv4interface;

    private JTextField dhcpIPv6interface;

    //NTP VARIABLES

    private JButton ntpStatus;
    private JButton startNTP;
    private JButton stopNTP;
    private JButton restartNTP;

    private JTextField NTPmaskIPv4;
    private JTextField NTPmaskIPv6;

    private JTextField NTPinterface;

    //DNS IPv4 pole
    private JTextField ntpIPbyte1;
    private JTextField ntpIPbyte2;
    private JTextField ntpIPbyte3;
    private JTextField ntpIPbyte4;

    //DNS IPv6 pole
    private JTextField ntpIPv6Hextet1;
    private JTextField ntpIPv6Hextet2;
    private JTextField ntpIPv6Hextet3;
    private JTextField ntpIPv6Hextet4;
    private JTextField ntpIPv6Hextet5;
    private JTextField ntpIPv6Hextet6;
    private JTextField ntpIPv6Hextet7;
    private JTextField ntpIPv6Hextet8;

    /**
     * Constructor for the ServerEmulatorGui object.
     */
    public ServerEmulatorGui() throws URISyntaxException, IOException {
        registerTestStateListener();
        ServerEmulatorTreeGuard.getInstance().registerListeners();
        addExitListener();

        if (System.getProperty("jmeter.home") == null) {
            File userDir = new File(System.getProperty("user.dir"));
            jmeterHomeDir = userDir.getAbsoluteFile().getParent();
        } else {
            jmeterHomeDir = System.getProperty("jmeter.home");
        }
        init();
        serverEmulatorCore = new ServerEmulatorCore(this, jmeterHomeDir);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public TestElement createTestElement() {
        ServerEmulator el = new ServerEmulator();
        modifyTestElement(el);
        return el;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void modifyTestElement(TestElement element) {
        configureTestElement(element);

        if (!serverEmulatorCore.isListenersRegistered()) {
            serverEmulatorCore.addActionRouterListeners();
        }
        if (!nsName.equals("") && !nsConfigured) {
            serverEmulatorCore.deleteNs(true);
        }
        element.setProperty(ServerEmulator.HTTPAUTOSTART, httpAutoStartCB.isSelected());
        element.setProperty(ServerEmulator.FTPAUTOSTART, ftpAutoStartCB.isSelected());
        element.setProperty(ServerEmulator.HTTPPORT, httpPortTF.getText());
        element.setProperty(ServerEmulator.SSLENABLED, enableSSLCB.isSelected());
        element.setProperty(ServerEmulator.HTMLSIZE, String.valueOf(htmlSize));
        element.setProperty(ServerEmulator.IPBYTE1, ipTFByte1.getText());
        element.setProperty(ServerEmulator.IPBYTE2, ipTFByte2.getText());
        element.setProperty(ServerEmulator.IPBYTE3, ipTFByte3.getText());
        element.setProperty(ServerEmulator.IPBYTE4START, ipTFByte4Start.getText());
        element.setProperty(ServerEmulator.IPBYTE4END, ipTFByte4End.getText());

        element.setProperty(ServerEmulator.ADVANCEDENABLED, enableAdvancedCB.isSelected());
        element.setProperty(ServerEmulator.STARTSERVERS, startServersTF.getText());
        element.setProperty(ServerEmulator.MAXREQUESTWORKERS, maxRequestWorkersTF.getText());
        element.setProperty(ServerEmulator.THREADSPERCHILD, threadsPerChildTF.getText());
        element.setProperty(ServerEmulator.MINSPARETHREADS, minSpareThreadsTF.getText());
        element.setProperty(ServerEmulator.MAXSPARETHREADS, maxSpareThreadsTF.getText());

        element.setProperty(ServerEmulator.NSCONFIGURED, nsConfigured); //tells the Network Analyzer that netns is configured
        element.setProperty(ServerEmulator.NSNAME, nsName);
        element.setProperty(ServerEmulator.LISTENDEVNAME, listenDevNameLbl.getText());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void configure(TestElement element) {
        super.configure(element);
        httpAutoStartCB.setSelected(element.getPropertyAsBoolean(ServerEmulator.HTTPAUTOSTART));
        ftpAutoStartCB.setSelected(element.getPropertyAsBoolean(ServerEmulator.FTPAUTOSTART));
        httpPortTF.setText(element.getPropertyAsString(ServerEmulator.HTTPPORT));
        enableSSLCB.setSelected(element.getPropertyAsBoolean(ServerEmulator.SSLENABLED));
        htmlSize = Double.parseDouble(element.getPropertyAsString(ServerEmulator.HTMLSIZE));
        ipTFByte1.setText(element.getPropertyAsString(ServerEmulator.IPBYTE1));
        ipTFByte2.setText(element.getPropertyAsString(ServerEmulator.IPBYTE2));
        ipTFByte3.setText(element.getPropertyAsString(ServerEmulator.IPBYTE3));
        ipTFByte4Start.setText(element.getPropertyAsString(ServerEmulator.IPBYTE4START));
        ipTFByte4End.setText(element.getPropertyAsString(ServerEmulator.IPBYTE4END));

        enableAdvancedCB.setSelected(element.getPropertyAsBoolean(ServerEmulator.ADVANCEDENABLED));
        startServersTF.setText(element.getPropertyAsString(ServerEmulator.STARTSERVERS));
        maxRequestWorkersTF.setText(element.getPropertyAsString(ServerEmulator.MAXREQUESTWORKERS));
        threadsPerChildTF.setText(element.getPropertyAsString(ServerEmulator.THREADSPERCHILD));
        minSpareThreadsTF.setText(element.getPropertyAsString(ServerEmulator.MINSPARETHREADS));
        maxSpareThreadsTF.setText(element.getPropertyAsString(ServerEmulator.MAXSPARETHREADS));
    }

    void setNsName(String nsName) {
        this.nsName = nsName;
    }

    /**
     * Shows status messages on GUI
     *
     * @param state - string to be displayed
     */
    public void showState(String state) {
        infoTextArea.append(state);
        infoTextArea.setCaretPosition(infoTextArea.getDocument().getLength());
    }

    void state(String state) {
        state(null, state);
    }

    void state(String type, String state) {
        state(null, type, state);
    }

    void state(Object caller, String state) {
        state(caller, null, state);
    }

    /**
     * Sends a string with a message about current state or action taken and logs the message
     *
     * @param caller object from which the message origins
     * @param type   informs about type of the message which may be info/warn/error
     * @param state  string to be displayed in GUI text area
     */
    void state(Object caller, String type, String state) {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        Calendar cal = Calendar.getInstance();
        String typeString = "";
        if (type == null) {
            type = "info";
        }
        String stateString;
        if (caller == null) {
            caller = "";
            stateString = state;
        } else {
            caller = caller.getClass().getSimpleName();
            stateString = caller + ": " + state;
        }

        switch (type) {
            case "info":
                log.info(stateString);
                typeString = "";
                break;
            case "warn":
                log.warn(stateString);
                typeString = "WARNING: ";
                break;
            case "error":
                log.error(stateString);
                typeString = "ERROR: ";
                break;
            default:
                log.error("Invalid state type");
        }
        showState(sdf.format(cal.getTime()) + "  " + caller + ": " + typeString + state + "\n");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getLabelResource() {
        return SERVER_EMULATOR_TITLE; // $NON-NLS-1$
    }

    /**
     * @return The name of component used in title, tree and name of the test
     */
    @Override
    public String getStaticLabel() {
        return JMeterUtils.getLocaleString(SERVER_EMULATOR_TITLE);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void clearData() {
        infoTextArea.setText(null);
        repaint();
    }

    /**
     * Initialize the GUI.
     */
    private void init() {
        this.setLayout(new GridBagLayout());
        Border margin = new EmptyBorder(10, 10, 5, 10);
        this.setBorder(margin);

        tabbedPane = new JTabbedPane(SwingConstants.TOP);

        //Creates main panel
        JPanel mainPanel = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        Border topBottomMargin = new EmptyBorder(10, 0, 5, 0);

        ServerEmulatorInputVerifier myVerifier = new ServerEmulatorInputVerifier();

        /////////Panel with settings of network namespace utilization //////////////
        JPanel netnsPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        netnsPanel.setBorder(BorderFactory.createCompoundBorder(topBottomMargin, BorderFactory.createEtchedBorder(EtchedBorder.LOWERED)));
        singleMachineCB = new JCheckBox(JMeterUtils.getLocaleString(SERVER_EMULATOR_SINGLE_MACHINE));
        singleMachineCB.addActionListener(this);

        singleMachineCB.setSelected(false);
        netnsPanel.add(singleMachineCB);
        listenCaptionLbl = new JLabel();
        netnsPanel.add(listenCaptionLbl);
        listenDevNameLbl = new JLabel();
        netnsPanel.add(listenDevNameLbl);

        ///////////Panel with HTTP server control buttons, config and html page generator settings //////////////
        JPanel HTTPPanel = new JPanel(new BorderLayout());
        HTTPPanel.setBorder(BorderFactory.createCompoundBorder(topBottomMargin, BorderFactory.createTitledBorder(JMeterUtils.getLocaleString(SERVER_EMULATOR_HTTP_SERVER))));

        //"Invisible" panel for layouting purpose
        JPanel HTTPRow1Panel = new JPanel(new FlowLayout(FlowLayout.LEADING));

        //Panel for HTTP controls for aesthetic purposes
        JPanel HTTPControlPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        //HTTPControlPanel.setBorder(BorderFactory.createCompoundBorder(topBottomMargin, BorderFactory.createTitledBorder("HTTP server control")));
        HTTPControlPanel.setBorder(BorderFactory.createTitledBorder(JMeterUtils.getLocaleString(SERVER_EMULATOR_SERVER_CONTROL)));

        httpAutoStartCB = new JCheckBox(JMeterUtils.getLocaleString(SERVER_EMULATOR_AUTOSTART));
        HTTPControlPanel.add(httpAutoStartCB);

        startHTTPServer.addActionListener(this);
        HTTPControlPanel.add(startHTTPServer);

        stopHTTPServer.addActionListener(this);
        HTTPControlPanel.add(stopHTTPServer);

        httpServerStatus.addActionListener(this);
        HTTPControlPanel.add(httpServerStatus);

        //////////////Adds HTTP control panel generator panel to HTTP Row1 panel
        HTTPRow1Panel.add(HTTPControlPanel);

        ///////////Panel with HTML generator settings //////////////
        JPanel htmlPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        htmlPanel.setBorder(BorderFactory.createTitledBorder(JMeterUtils.getLocaleString(SERVER_EMULATOR_GENERATOR_SETTINGS)));

        //Spinner and labels for sample page genertion size
        JLabel htmlSizeLabel = new JLabel(JMeterUtils.getLocaleString(SERVER_EMULATOR_PAGE_SIZE));
        htmlPanel.add(htmlSizeLabel);
        SpinnerModel model = new SpinnerNumberModel(10.0, 0.3, 10000.0, 10.0);
        htmlSize = 10.0 * 1024; //Should be set to the same value as htmlSizeSpinner default
        htmlSizeSpinner = new JSpinner(model);
        htmlSizeSpinner.addChangeListener(this);
        htmlPanel.add(htmlSizeSpinner);

        JLabel sizeUnitsLabel = new JLabel(" kiB");
        htmlPanel.add(sizeUnitsLabel);

        //////////////Adds HTML generator panel to HTTP Row1 panel
        HTTPRow1Panel.add(htmlPanel);

        ///////////Panel with HTTP server configuration//////////////
        JPanel HTTPconfigPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        HTTPconfigPanel.setBorder(BorderFactory.createCompoundBorder(topBottomMargin, BorderFactory.createTitledBorder("Server configuration")));

        JLabel HTTPPortLabel = new JLabel(JMeterUtils.getLocaleString(SERVER_EMULATOR_HTTP_PORT));
        HTTPconfigPanel.add(HTTPPortLabel);
        httpPortTF = new JTextField("80", 5);
        httpPortTF.setName("HTTPPortTF");
        httpPortTF.setInputVerifier(myVerifier);
        HTTPconfigPanel.add(httpPortTF);

        enableSSLCB = new JCheckBox(JMeterUtils.getLocaleString(SERVER_EMULATOR_ENABLE_SSL));
        HTTPconfigPanel.add(enableSSLCB);

        JSeparator vertLine = new JSeparator(SwingConstants.VERTICAL);
        vertLine.setPreferredSize(new Dimension(3, 15));
        HTTPconfigPanel.add(vertLine);

        JLabel ipLabel = new JLabel(JMeterUtils.getLocaleString(SERVER_EMULATOR_IP));
        HTTPconfigPanel.add(ipLabel);

        ipTFByte1 = new JTextField("192", 3);
        ipTFByte1.setName("ipTFByte");
        ipTFByte1.setInputVerifier(myVerifier);
        HTTPconfigPanel.add(ipTFByte1);
        JLabel dotLabel = new JLabel(".");
        HTTPconfigPanel.add(dotLabel);

        ipTFByte2 = new JTextField("168", 3);
        ipTFByte2.setName("ipTFByte");
        ipTFByte2.setInputVerifier(myVerifier);
        HTTPconfigPanel.add(ipTFByte2);
        dotLabel = new JLabel(".");
        HTTPconfigPanel.add(dotLabel);

        ipTFByte3 = new JTextField("50", 3);
        ipTFByte3.setName("ipTFByte");
        ipTFByte3.setInputVerifier(myVerifier);
        HTTPconfigPanel.add(ipTFByte3);
        dotLabel = new JLabel(".");
        HTTPconfigPanel.add(dotLabel);

        ipTFByte4Start = new JTextField("128", 3);
        ipTFByte4Start.setName("ipTFByte");
        ipTFByte4Start.setInputVerifier(myVerifier);
        HTTPconfigPanel.add(ipTFByte4Start);
        JLabel dashLabel = new JLabel("-");
        HTTPconfigPanel.add(dashLabel);

        ipTFByte4End = new JTextField(3);
        ipTFByte4End.setName("ipTFByte4End");
        ipTFByte4End.setInputVerifier(myVerifier);
        HTTPconfigPanel.add(ipTFByte4End);

        //////////////Adds HTTP Row1 panel and config panel to main HTTP panel
        HTTPPanel.add(HTTPRow1Panel, BorderLayout.NORTH);

        /////////Adds HTTP config panel to main HTTP panel
        HTTPPanel.add(HTTPconfigPanel, BorderLayout.SOUTH);

        ///////////Panel with FTP server controls//////////////
        JPanel FTPPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        FTPPanel.setBorder(BorderFactory.createCompoundBorder(topBottomMargin, BorderFactory.createTitledBorder("FTP server control")));

        ftpAutoStartCB = new JCheckBox(JMeterUtils.getLocaleString(SERVER_EMULATOR_AUTOSTART));
        FTPPanel.add(ftpAutoStartCB);

        startFTPServer.addActionListener(this);
        FTPPanel.add(startFTPServer);

        stopFTPServer.addActionListener(this);
        FTPPanel.add(stopFTPServer);

        ftpServerStatus.addActionListener(this);
        FTPPanel.add(ftpServerStatus);

        //////////////Adds Network Namespace panel to main panel///////////
        c.fill = GridBagConstraints.HORIZONTAL;
        c.insets = new Insets(0, 0, 0, 0);
        c.weightx = 1.0;
        c.gridx = 0;
        c.gridy = 0;
        mainPanel.add(netnsPanel, c);

        //////////////Adds HTTP panel to main panel///////////
        c.fill = GridBagConstraints.HORIZONTAL;
        c.insets = new Insets(0, 0, 0, 0);
        c.weightx = 1.0;
        c.gridx = 0;
        c.gridy = 1;
        mainPanel.add(HTTPPanel, c);

        //////////////Adds FTP panel to main panel///////////
        c.fill = GridBagConstraints.HORIZONTAL;
        c.insets = new Insets(0, 0, 0, 0);
        c.weightx = 1.0;
        c.gridx = 0;
        c.gridy = 2;
        mainPanel.add(FTPPanel, c);

        //////////////////////////////////Add main panel to a first tab////////////////////////////////////////////
        tabbedPane.addTab(JMeterUtils.getLocaleString(SERVER_EMULATOR_COMMON_CONTROLS), mainPanel);

        //Creates panel with advanced Apache HTTP server settings
        ToolTipManager.sharedInstance().setDismissDelay(20000);

        advancedPanel = new JPanel(new GridBagLayout());
        advancedPanel.setBorder(BorderFactory.createTitledBorder(JMeterUtils.getLocaleString(SERVER_EMULATOR_ADVANCED_BORDER)));

        enableAdvancedCB = new JCheckBox(JMeterUtils.getLocaleString(SERVER_EMULATOR_ENABLE_ADVANCED));
        enableAdvancedCB.addActionListener(this);
        c.fill = GridBagConstraints.HORIZONTAL;
        c.insets = new Insets(10, 5, 10, 5);
        c.weightx = 0;
        c.gridwidth = 4;
        c.gridx = 0;
        c.gridy = 0;
        advancedPanel.add(enableAdvancedCB, c);

        JLabel startServersLabel = new JLabel(JMeterUtils.getLocaleString(SERVER_EMULATOR_ADVANCED_SUBPROCESSES));
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.LINE_START;
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 4;
        c.gridx = 0;
        c.gridy = 1;
        advancedPanel.add(startServersLabel, c);
        startServersTF = new JTextField("3", 5);
        startServersTF.setEnabled(false);
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 1;
        c.gridx = 3;
        c.gridy = 1;
        advancedPanel.add(startServersTF, c);

        JLabel threadsPerChildLabel = new JLabel(JMeterUtils.getLocaleString(SERVER_EMULATOR_ADVANCED_THREADS_PER_SUBPROCESS));
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 1;
        c.gridx = 0;
        c.gridy = 2;
        advancedPanel.add(threadsPerChildLabel, c);
        threadsPerChildTF = new JTextField("25", 5);
        threadsPerChildTF.setEnabled(false);
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 1;
        c.gridx = 1;
        c.gridy = 2;
        advancedPanel.add(threadsPerChildTF, c);

        JLabel maxRequestWorkersLabel = new JLabel(JMeterUtils.getLocaleString(SERVER_EMULATOR_ADVANCED_MAX_THREADS));
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 1;
        c.gridx = 2;
        c.gridy = 2;
        advancedPanel.add(maxRequestWorkersLabel, c);
        maxRequestWorkersTF = new JTextField("400", 5);
        maxRequestWorkersTF.setEnabled(false);
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 1;
        c.gridx = 3;
        c.gridy = 2;
        advancedPanel.add(maxRequestWorkersTF, c);

        c.gridx = 0;
        c.gridy = 3;
        advancedPanel.add(Box.createVerticalStrut(15), c);

        ////Panel for settings spare workers limits
        JLabel spareThreadsLabel = new JLabel(JMeterUtils.getLocaleString(SERVER_EMULATOR_ADVANCED_SPARE_THREADS_TITLE));
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 4;
        c.gridx = 0;
        c.gridy = 4;
        advancedPanel.add(spareThreadsLabel, c);

        JLabel minSpareThreadsLabel = new JLabel(JMeterUtils.getLocaleString(SERVER_EMULATOR_ADVANCED_MIN_SPARE_THREADS));
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 1;
        c.gridx = 0;
        c.gridy = 5;
        advancedPanel.add(minSpareThreadsLabel, c);
        minSpareThreadsTF = new JTextField("75", 5);
        minSpareThreadsTF.setEnabled(false);
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 1;
        c.gridx = 1;
        c.gridy = 5;
        advancedPanel.add(minSpareThreadsTF, c);

        JLabel maxSpareThreadsLabel = new JLabel(JMeterUtils.getLocaleString(SERVER_EMULATOR_ADVANCED_MAX_SPARE_THREADS));
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 1;
        c.gridx = 2;
        c.gridy = 5;
        advancedPanel.add(maxSpareThreadsLabel, c);
        maxSpareThreadsTF = new JTextField("250", 5);
        maxSpareThreadsTF.setEnabled(false);
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 1;
        c.gridx = 3;
        c.gridy = 5;
        advancedPanel.add(maxSpareThreadsTF, c);

        c.gridx = 0;
        c.gridy = 6;
        advancedPanel.add(Box.createVerticalStrut(15), c);

        JLabel hardLimitsInfoLbl = new JLabel(new ImageIcon(getClass().getResource("/images/question-small.png")));
        hardLimitsInfoLbl.setToolTipText(JMeterUtils.getLocaleString(SERVER_EMULATOR_HARD_LIMIT_INFO));
        c.insets = new Insets(10, 5, 10, 5);
        c.gridwidth = 1;
        c.gridx = 0;
        c.gridy = 7;
        advancedPanel.add(hardLimitsInfoLbl, c);

        defaultsBtn.addActionListener(this);
        c.anchor = GridBagConstraints.LINE_END;
        c.insets = new Insets(5, 5, 5, 5);
        c.gridwidth = 2;
        c.gridx = 2;
        c.gridy = 7;
        advancedPanel.add(defaultsBtn, c);

        ///To anchor whole component set to top-left corner
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1;
        c.weighty = 1;
        c.gridx = 4;
        c.gridy = 8;
        advancedPanel.add(Box.createHorizontalStrut(1), c);
        c.weightx = 0;
        c.weighty = 0;


        //////////////////////////////////Add advanced panel to a second tab////////////////////////////////////////////        
        tabbedPane.addTab(JMeterUtils.getLocaleString(SERVER_EMULATOR_ADVANCED), advancedPanel);



        //Additional services------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        ToolTipManager.sharedInstance().setDismissDelay(20000);

        //hlavní panely

        //DNS hlavní panel
        JPanel MainPanelDNS = new JPanel(new GridBagLayout());
        MainPanelDNS.setLayout(new BoxLayout(MainPanelDNS, BoxLayout.Y_AXIS));

        //DHCP hlavní panel
        JPanel MainPanelDHCP = new JPanel(new GridBagLayout());
        MainPanelDHCP.setLayout(new BoxLayout(MainPanelDHCP, BoxLayout.Y_AXIS));

        //NTP hlavní panel
        JPanel MainPanelNTP = new JPanel(new GridBagLayout());
        MainPanelNTP.setLayout(new BoxLayout(MainPanelNTP, BoxLayout.Y_AXIS));

        //NTP BUTTONS

        JPanel NTPpanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        NTPpanel.setBorder(BorderFactory.createTitledBorder("NTP Server controls"));

        startNTP = new JButton("Start NTP");
        startNTP.addActionListener(this);
        NTPpanel.add(startNTP);

        stopNTP = new JButton("Stop NTP");
        stopNTP.addActionListener(this);
        NTPpanel.add(stopNTP);

        restartNTP = new JButton("Restart NTP");
        restartNTP.addActionListener(this);
        NTPpanel.add(restartNTP);

        ntpStatus = new JButton("Display NTP status");
        ntpStatus.addActionListener(this);
        NTPpanel.add(ntpStatus);

        JPanel NTPConfigPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        NTPConfigPanel.setBorder(BorderFactory.createTitledBorder("NTP Server configration"));

        JLabel NTPlabel = new JLabel(JMeterUtils.getLocaleString("NTP listen on interface "));
        NTPConfigPanel.add(NTPlabel);

        NTPinterface = new JTextField("", 5);
        NTPinterface.setName("NTPinterface");
        NTPConfigPanel.add(NTPinterface);

        //NTP IPv4

        JPanel NTPServerSettingsPanelIPv4 = new JPanel(new FlowLayout(FlowLayout.LEADING));

        JLabel NTPIPv4Label = new JLabel(JMeterUtils.getLocaleString("IPv4: "));
        NTPServerSettingsPanelIPv4.add(NTPIPv4Label);

        ntpIPbyte1 = new JTextField("", 3);
        ntpIPbyte1.setName("ipTFByte");
        NTPServerSettingsPanelIPv4.add(ntpIPbyte1);
        JLabel NTPdotLabel = new JLabel(".");
        NTPServerSettingsPanelIPv4.add(NTPdotLabel);

        ntpIPbyte2 = new JTextField("", 3);
        ntpIPbyte2.setName("ipTFByte");
        NTPServerSettingsPanelIPv4.add(ntpIPbyte2);
        NTPdotLabel = new JLabel(".");
        NTPServerSettingsPanelIPv4.add(NTPdotLabel);

        ntpIPbyte3 = new JTextField("", 3);
        ntpIPbyte3.setName("ipTFByte");
        NTPServerSettingsPanelIPv4.add(ntpIPbyte3);
        NTPdotLabel = new JLabel(".");
        NTPServerSettingsPanelIPv4.add(NTPdotLabel);

        ntpIPbyte4 = new JTextField("", 3);
        ntpIPbyte4.setName("ipTFByte");
        NTPServerSettingsPanelIPv4.add(ntpIPbyte4);

        JLabel maskNTPipv4 = new JLabel("/");
        NTPServerSettingsPanelIPv4.add(maskNTPipv4);

        NTPmaskIPv4 = new JTextField("", 3);
        NTPmaskIPv4.setName("NTPmaskIPv4");
        NTPServerSettingsPanelIPv4.add(NTPmaskIPv4);


        //NTP IPv6

        JPanel NTPServerSettingsPanelIPv6 = new JPanel(new FlowLayout(FlowLayout.LEADING));

        JLabel NTPIPv6Label = new JLabel(JMeterUtils.getLocaleString("IPv6: "));
        NTPServerSettingsPanelIPv6.add(NTPIPv6Label);

        ntpIPv6Hextet1 = new JTextField("", 3);
        ntpIPv6Hextet1.setName("ipTFByte");
        NTPServerSettingsPanelIPv6.add(ntpIPv6Hextet1);
        JLabel NTPcolonLabel = new JLabel(":");
        NTPServerSettingsPanelIPv6.add(NTPcolonLabel);

        ntpIPv6Hextet2 = new JTextField("", 3);
        ntpIPv6Hextet2.setName("ipTFByte");
        NTPServerSettingsPanelIPv6.add(ntpIPv6Hextet2);
        NTPcolonLabel = new JLabel(":");
        NTPServerSettingsPanelIPv6.add(NTPcolonLabel);

        ntpIPv6Hextet3 = new JTextField("", 3);
        ntpIPv6Hextet3.setName("ipTFByte");
        NTPServerSettingsPanelIPv6.add(ntpIPv6Hextet3);
        NTPcolonLabel = new JLabel(":");
        NTPServerSettingsPanelIPv6.add(NTPcolonLabel);

        ntpIPv6Hextet4 = new JTextField("", 3);
        ntpIPv6Hextet4.setName("ipTFByte");
        NTPServerSettingsPanelIPv6.add(ntpIPv6Hextet4);
        NTPcolonLabel = new JLabel(":");
        NTPServerSettingsPanelIPv6.add(NTPcolonLabel);

        ntpIPv6Hextet5 = new JTextField("", 3);
        ntpIPv6Hextet5.setName("ipTFByte");
        NTPServerSettingsPanelIPv6.add(ntpIPv6Hextet5);
        NTPcolonLabel = new JLabel(":");
        NTPServerSettingsPanelIPv6.add(NTPcolonLabel);

        ntpIPv6Hextet6 = new JTextField("", 3);
        ntpIPv6Hextet6.setName("ipTFByte");
        NTPServerSettingsPanelIPv6.add(ntpIPv6Hextet6);
        NTPcolonLabel = new JLabel(":");
        NTPServerSettingsPanelIPv6.add(NTPcolonLabel);

        ntpIPv6Hextet7 = new JTextField("", 3);
        ntpIPv6Hextet7.setName("ipTFByte");
        NTPServerSettingsPanelIPv6.add(ntpIPv6Hextet7);
        NTPcolonLabel = new JLabel(":");
        NTPServerSettingsPanelIPv6.add(NTPcolonLabel);

        ntpIPv6Hextet8 = new JTextField("", 3);
        ntpIPv6Hextet8.setName("ipTFByte");
        NTPServerSettingsPanelIPv6.add(ntpIPv6Hextet8);

        JLabel maskNTPipv6 = new JLabel("/");
        NTPServerSettingsPanelIPv6.add(maskNTPipv6);

        NTPmaskIPv6 = new JTextField("", 3);
        NTPmaskIPv6.setName("NTPmaskIPv4");
        NTPServerSettingsPanelIPv6.add(NTPmaskIPv6);

        //COMMON BUTTONS

        //Nastavení IP adresy na rozhraní
        JPanel CommonServerSettingsPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        CommonServerSettingsPanel.setBorder(BorderFactory.createTitledBorder("Add/delete IP to/from interface"));

        //IPv4

        showIPtoInterface= new JButton("Show");
        showIPtoInterface.addActionListener(this);
        CommonServerSettingsPanel.add(showIPtoInterface);

        addIPtoInterface = new JButton("Add ");
        addIPtoInterface.addActionListener(this);
        CommonServerSettingsPanel.add(addIPtoInterface);

        deleteIPtoInterface = new JButton("Delete ");
        deleteIPtoInterface.addActionListener(this);
        CommonServerSettingsPanel.add(deleteIPtoInterface);

        JLabel CommonInterfaceLabel = new JLabel(JMeterUtils.getLocaleString("On interface: "));
        CommonServerSettingsPanel.add(CommonInterfaceLabel);

        commonInterface = new JTextField("", 5);
        commonInterface.setName("CommonInterface");
        CommonServerSettingsPanel.add(commonInterface);

        JPanel CommonServerSettingsPanelIPv4 = new JPanel(new FlowLayout(FlowLayout.LEADING));

        JLabel CommonIPLabel = new JLabel(JMeterUtils.getLocaleString("IPv4: "));
        CommonServerSettingsPanelIPv4.add(CommonIPLabel);

        //IPv4

        commonIPbyte1 = new JTextField(3);
        commonIPbyte1.setName("ipTFByte");
        CommonServerSettingsPanelIPv4.add(commonIPbyte1);
        JLabel COMMONdotLabel = new JLabel(".");
        CommonServerSettingsPanelIPv4.add(COMMONdotLabel);

        commonIPbyte2 = new JTextField("", 3);
        commonIPbyte2.setName("ipTFByte");
        CommonServerSettingsPanelIPv4.add(commonIPbyte2);
        COMMONdotLabel = new JLabel(".");
        CommonServerSettingsPanelIPv4.add(COMMONdotLabel);

        commonIPbyte3 = new JTextField("", 3);
        commonIPbyte3.setName("ipTFByte");
        CommonServerSettingsPanelIPv4.add(commonIPbyte3);
        COMMONdotLabel = new JLabel(".");
        CommonServerSettingsPanelIPv4.add(COMMONdotLabel);

        commonIPbyte4 = new JTextField("", 3);
        commonIPbyte4.setName("ipTFByte");
        CommonServerSettingsPanelIPv4.add(commonIPbyte4);

        JLabel CommonIPv4MaskLabel = new JLabel(JMeterUtils.getLocaleString("/"));
        CommonServerSettingsPanelIPv4.add(CommonIPv4MaskLabel);

        commonIPv4Mask = new JTextField("", 3);
        commonIPv4Mask.setName("ipTFByte");
        CommonServerSettingsPanelIPv4.add(commonIPv4Mask);


        //IPv6

        JPanel CommonServerSettingsPanelIPv6 = new JPanel(new FlowLayout(FlowLayout.LEADING));

        JLabel CommonIPv6Label = new JLabel(JMeterUtils.getLocaleString("IPv6: "));
        CommonServerSettingsPanelIPv6.add(CommonIPv6Label);

        commonIPv6Hextet1 = new JTextField( 3);
        commonIPv6Hextet1.setName("ipTFByte");
        CommonServerSettingsPanelIPv6.add(commonIPv6Hextet1);
        JLabel COMMONcolonLabel = new JLabel(":");
        CommonServerSettingsPanelIPv6.add(COMMONcolonLabel);

        commonIPv6Hextet2 = new JTextField("", 3);
        commonIPv6Hextet2.setName("ipTFByte");
        CommonServerSettingsPanelIPv6.add(commonIPv6Hextet2);
        COMMONcolonLabel = new JLabel(":");
        CommonServerSettingsPanelIPv6.add(COMMONcolonLabel);

        commonIPv6Hextet3 = new JTextField("", 3);
        commonIPv6Hextet3.setName("ipTFByte");
        CommonServerSettingsPanelIPv6.add(commonIPv6Hextet3);
        COMMONcolonLabel = new JLabel(":");
        CommonServerSettingsPanelIPv6.add(COMMONcolonLabel);

        commonIPv6Hextet4 = new JTextField("", 3);
        commonIPv6Hextet4.setName("ipTFByte");
        CommonServerSettingsPanelIPv6.add(commonIPv6Hextet4);
        COMMONcolonLabel = new JLabel(":");
        CommonServerSettingsPanelIPv6.add(COMMONcolonLabel);

        commonIPv6Hextet5 = new JTextField("", 3);
        commonIPv6Hextet5.setName("ipTFByte");
        CommonServerSettingsPanelIPv6.add(commonIPv6Hextet5);
        COMMONcolonLabel = new JLabel(":");
        CommonServerSettingsPanelIPv6.add(COMMONcolonLabel);

        commonIPv6Hextet6 = new JTextField("", 3);
        commonIPv6Hextet6.setName("ipTFByte");
        CommonServerSettingsPanelIPv6.add(commonIPv6Hextet6);
        COMMONcolonLabel = new JLabel(":");
        CommonServerSettingsPanelIPv6.add(COMMONcolonLabel);

        commonIPv6Hextet7 = new JTextField("", 3);
        commonIPv6Hextet7.setName("ipTFByte");
        CommonServerSettingsPanelIPv6.add(commonIPv6Hextet7);
        COMMONcolonLabel = new JLabel(":");
        CommonServerSettingsPanelIPv6.add(COMMONcolonLabel);

        commonIPv6Hextet8 = new JTextField("", 3);
        commonIPv6Hextet8.setName("ipTFByte");
        CommonServerSettingsPanelIPv6.add(commonIPv6Hextet8);

        JLabel CommonIPv6MaskLabel = new JLabel(JMeterUtils.getLocaleString("/"));
        CommonServerSettingsPanelIPv6.add(CommonIPv6MaskLabel);

        commonIPv6Mask = new JTextField("", 3);
        commonIPv6Mask.setName("ipTFByte");
        CommonServerSettingsPanelIPv6.add(commonIPv6Mask);


        //pomocný DNS panel
        JPanel DNSCommonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        DNSCommonPanel.setBorder(BorderFactory.createTitledBorder("DNS Server controls"));

        //DNS tlačítka
        startDNS = new JButton("Start DNS");
        startDNS.addActionListener(this);
        DNSCommonPanel.add(startDNS);

        stopDNS = new JButton("Stop DNS");
        stopDNS.addActionListener(this);
        DNSCommonPanel.add(stopDNS);

        restartDNS = new JButton("Restart DNS");
        restartDNS.addActionListener(this);
        DNSCommonPanel.add(restartDNS);


        dnsStatus = new JButton("Display DNS status");
        dnsStatus.addActionListener(this);
        DNSCommonPanel.add(dnsStatus);


        ///////////Nastaveni IPv4, IPv6 a portu pro DNS//////////////

        JPanel DNSconfigPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        DNSconfigPanel.setBorder(BorderFactory.createCompoundBorder(topBottomMargin, BorderFactory.createTitledBorder("DNS Server configuration")));

        JLabel DNSport = new JLabel(JMeterUtils.getLocaleString("DNS listen on port: "));
        DNSconfigPanel.add(DNSport);
        dnsPORT = new JTextField("53", 5);
        dnsPORT.setName("DNSPortTF");
        DNSconfigPanel.add(dnsPORT);


//        enableSSLCB = new JCheckBox(JMeterUtils.getLocaleString(SERVER_EMULATOR_ENABLE_SSL));
//        HTTPconfigPanel.add(enableSSLCB);

//        JSeparator vertLine = new JSeparator(SwingConstants.VERTICAL);
//        vertLine.setPreferredSize(new Dimension(3, 15));
//        HTTPconfigPanel.add(vertLine);

        JPanel DNSServerSettingsPanelIPv4 = new JPanel(new FlowLayout(FlowLayout.LEADING));

        JLabel DNSipLabel = new JLabel(JMeterUtils.getLocaleString("IPv4: "));
        DNSServerSettingsPanelIPv4.add(DNSipLabel);

        dnsIPbyte1 = new JTextField("192", 3);
        dnsIPbyte1.setName("ipTFByte");
        DNSServerSettingsPanelIPv4.add(dnsIPbyte1);
        JLabel DNSdotLabel = new JLabel(".");
        DNSServerSettingsPanelIPv4.add(DNSdotLabel);

        dnsIPbyte2 = new JTextField("168", 3);
        dnsIPbyte2.setName("ipTFByte");
        DNSServerSettingsPanelIPv4.add(dnsIPbyte2);
        DNSdotLabel = new JLabel(".");
        DNSServerSettingsPanelIPv4.add(DNSdotLabel);

        dnsIPbyte3 = new JTextField("56", 3);
        dnsIPbyte3.setName("ipTFByte");
        DNSServerSettingsPanelIPv4.add(dnsIPbyte3);
        DNSdotLabel = new JLabel(".");
        DNSServerSettingsPanelIPv4.add(DNSdotLabel);

        dnsIPbyte4 = new JTextField("103", 3);
        dnsIPbyte4.setName("ipTFByte");
        DNSServerSettingsPanelIPv4.add(dnsIPbyte4);


        // Pole pro IPv6

        JPanel DNSServerSettingsPanelIPv6 = new JPanel(new FlowLayout(FlowLayout.LEADING));

        JLabel DNSIPv6Label = new JLabel(JMeterUtils.getLocaleString("IPv6: "));
        DNSServerSettingsPanelIPv6.add(DNSIPv6Label);

        dnsIPv6Hextet1 = new JTextField("2001", 3);
        dnsIPv6Hextet1.setName("ipTFByte");
        DNSServerSettingsPanelIPv6.add(dnsIPv6Hextet1);
        JLabel DNScolonLabel = new JLabel(":");
        DNSServerSettingsPanelIPv6.add(DNScolonLabel);

        dnsIPv6Hextet2 = new JTextField("0db8", 3);
        dnsIPv6Hextet2.setName("ipTFByte");
        DNSServerSettingsPanelIPv6.add(dnsIPv6Hextet2);
        DNScolonLabel = new JLabel(":");
        DNSServerSettingsPanelIPv6.add(DNScolonLabel);

        dnsIPv6Hextet3 = new JTextField("85a3", 3);
        dnsIPv6Hextet3.setName("ipTFByte");
        DNSServerSettingsPanelIPv6.add(dnsIPv6Hextet3);
        DNScolonLabel = new JLabel(":");
        DNSServerSettingsPanelIPv6.add(DNScolonLabel);

        dnsIPv6Hextet4 = new JTextField("0000", 3);
        dnsIPv6Hextet4.setName("ipTFByte");
        DNSServerSettingsPanelIPv6.add(dnsIPv6Hextet4);
        DNScolonLabel = new JLabel(":");
        DNSServerSettingsPanelIPv6.add(DNScolonLabel);

        dnsIPv6Hextet5 = new JTextField("0000", 3);
        dnsIPv6Hextet5.setName("ipTFByte");
        DNSServerSettingsPanelIPv6.add(dnsIPv6Hextet5);
        DNScolonLabel = new JLabel(":");
        DNSServerSettingsPanelIPv6.add(DNScolonLabel);

        dnsIPv6Hextet6 = new JTextField("8a2e", 3);
        dnsIPv6Hextet6.setName("ipTFByte");
        DNSServerSettingsPanelIPv6.add(dnsIPv6Hextet6);
        DNScolonLabel = new JLabel(":");
        DNSServerSettingsPanelIPv6.add(DNScolonLabel);

        dnsIPv6Hextet7 = new JTextField("0370", 3);
        dnsIPv6Hextet7.setName("ipTFByte");
        DNSServerSettingsPanelIPv6.add(dnsIPv6Hextet7);
        DNScolonLabel = new JLabel(":");
        DNSServerSettingsPanelIPv6.add(DNScolonLabel);

        dnsIPv6Hextet8 = new JTextField("7334", 3);
        dnsIPv6Hextet8.setName("ipTFByte");
        DNSServerSettingsPanelIPv6.add(dnsIPv6Hextet8);

        //pomocný DNSSEC panel
        JPanel DNSSECPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        DNSSECPanel.setBorder(BorderFactory.createTitledBorder("Domain Name System Security Extensions"));

        dnsSEC = new JCheckBox(JMeterUtils.getLocaleString("Enable DNSSEC validation"));
        DNSSECPanel.setBorder(BorderFactory.createTitledBorder("Domain Name System Security Extensions"));
        DNSSECPanel.add(dnsSEC);

        //pomocný DHCP panel
        JPanel DHCPpanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        DHCPpanel.setBorder(BorderFactory.createTitledBorder("DHCP Server controls"));

        //DHCP tlačítka
        startDHCP = new JButton("Start DHCP");
        startDHCP.addActionListener(this);
        DHCPpanel.add(startDHCP);

        stopDHCP = new JButton("Stop DHCP");
        stopDHCP.addActionListener(this);
        DHCPpanel.add(stopDHCP);

        restartDHCP = new JButton("Restart DHCP");
        restartDHCP.addActionListener(this);
        DHCPpanel.add(restartDHCP);

        dhcpStatus = new JButton("Display DHCP status");
        dhcpStatus.addActionListener(this);
        DHCPpanel.add(dhcpStatus);

        displayUsedPorts = new JButton("Display used DHCP ports");
        displayUsedPorts.addActionListener(this);
        DHCPpanel.add(displayUsedPorts);

        displayDHCPattachedIPs = new JButton("Display attached DHCP IP addresses");
        displayDHCPattachedIPs.addActionListener(this);
        DHCPpanel.add(displayDHCPattachedIPs);



        //Tlačítka pro nastavení rozhraní pro DHCP

        JPanel DHCPconfigPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        DHCPconfigPanel.setBorder(BorderFactory.createCompoundBorder(topBottomMargin, BorderFactory.createTitledBorder("DHCP Server configuration")));

        JLabel DHCPports = new JLabel(JMeterUtils.getLocaleString("DHCP listen on port or delete port(PID):  "));
        DHCPconfigPanel.add(DHCPports);
        portsDHCP = new JTextField("67", 5);
        portsDHCP.setName("DHCPinterfaceIPv4");
        DHCPconfigPanel.add(portsDHCP);

        //Add port
        addDHCPport = new JButton("Add DHCP port");
        addDHCPport.addActionListener(this);
        DHCPconfigPanel.add(addDHCPport);

        //Delete port
        deleteDHCPport = new JButton("Delete DHCP port PID");
        deleteDHCPport.addActionListener(this);
        DHCPconfigPanel.add(deleteDHCPport);


        //DHCP IPv4 interfaces
        JLabel DHCPinterfaceIPv4 = new JLabel(JMeterUtils.getLocaleString("| interfaces: IPv4: "));
        DHCPconfigPanel.add(DHCPinterfaceIPv4);
        dhcpIPv4interface = new JTextField("enp0s8", 5);
        dhcpIPv4interface.setName("DHCPinterfaceIPv4");
        DHCPconfigPanel.add(dhcpIPv4interface);

        JLabel DHCPinterfaceIPv4Label = new JLabel(JMeterUtils.getLocaleString("| IPv6: "));
        DHCPconfigPanel.add(DHCPinterfaceIPv4Label);

        //DHCP IPv6 interfaces
        dhcpIPv6interface = new JTextField("enp0s8", 5);
        dhcpIPv6interface.setName("DHCPinterfaceIPv6");
        DHCPconfigPanel.add(dhcpIPv6interface);

        //přidání přídavných panelů do hlavního panelu
        MainPanelDNS.add(DNSCommonPanel);
        MainPanelDNS.add(DNSconfigPanel);
        MainPanelDNS.add(DNSServerSettingsPanelIPv4);
        MainPanelDNS.add(DNSServerSettingsPanelIPv6);
        MainPanelDNS.add(DNSSECPanel);

        MainPanelDHCP.add(CommonServerSettingsPanel);
        MainPanelDHCP.add(CommonServerSettingsPanelIPv4);
        MainPanelDHCP.add(CommonServerSettingsPanelIPv6);
        MainPanelDHCP.add(DHCPpanel);
        MainPanelDHCP.add(DHCPconfigPanel);

        MainPanelNTP.add(NTPpanel);
        MainPanelNTP.add(NTPConfigPanel);
        MainPanelNTP.add(NTPServerSettingsPanelIPv4);
        MainPanelNTP.add(NTPServerSettingsPanelIPv6);


        //////////////////////////////////Přidání hlavních panelů do záložky////////////////////////////////////////////
        tabbedPane.addTab(JMeterUtils.getLocaleString("Domain Name System"), MainPanelDNS);
        tabbedPane.addTab(JMeterUtils.getLocaleString("Dynamic Host Configuration Protocol"), MainPanelDHCP);
        tabbedPane.addTab(JMeterUtils.getLocaleString("Network Time Protocol"), MainPanelNTP);
        //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------





        infoTextArea = new JTextArea(15, 50);
        infoTextArea.setLineWrap(true);
        infoTextArea.setWrapStyleWord(true);
        infoTextArea.setEditable(false);
        infoTextArea.setAutoscrolls(true);

        JScrollPane textScrollPane = new JScrollPane(infoTextArea);
        textScrollPane.setAutoscrolls(true);

        // Add a title panel, the tabbed pane and the text area to main frame
        c.fill = GridBagConstraints.HORIZONTAL;
        c.insets = new Insets(0, 0, 0, 0);
        c.gridwidth = 1;
        c.weightx = 1.0;
        c.gridx = 0;
        c.gridy = 0;
        this.add(makeTitlePanel(), c);

        c.fill = GridBagConstraints.HORIZONTAL;
        c.insets = new Insets(0, 0, 0, 0);
        c.gridwidth = 1;
        c.weightx = 1.0;
        c.gridx = 0;
        c.gridy = 1;
        this.add(tabbedPane, c);

        c.fill = GridBagConstraints.BOTH;
        c.insets = new Insets(0, 0, 0, 0);
        c.gridwidth = 1;
        c.weightx = 1.0;
        c.weighty = 1.0;
        c.gridx = 0;
        c.gridy = 2;
        this.add(textScrollPane, c);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        if (source == startHTTPServer) {
            startHTTPServer();
        } else if (source == stopHTTPServer) {
            stopHTTPServer(false);
        } else if (source == httpServerStatus) {
            serverEmulatorCore.getHTTPServerStatus(nsConfigured);
        } else if (source == startFTPServer) {
            startFTPServer();
        } else if (source == stopFTPServer) {
            stopFTPServer(false);
        } else if (source == ftpServerStatus) {
            serverEmulatorCore.getFTPServerStatus(nsConfigured);
        } else if (source == enableAdvancedCB) {
            enableAdvancedHTTPOptions(enableAdvancedCB.isSelected());
        } else if (source == defaultsBtn) {
            startServersTF.setText("3");
            maxRequestWorkersTF.setText("400");
            threadsPerChildTF.setText("25");
            minSpareThreadsTF.setText("75");
            maxSpareThreadsTF.setText("250");
        } else if (source == singleMachineCB) {
            if (singleMachineCB.isSelected()) {
                //Creates a modal dialog box to let the user choose interface for listening
                JPanel rbPanel = new JPanel();
                rbPanel.setLayout(new BoxLayout(rbPanel, BoxLayout.PAGE_AXIS));

                ButtonGroup rbGroup = new ButtonGroup();

                List<String> validDevNames = getValidDevNames();
                for (String devName : validDevNames) {
                    JRadioButton rb = new JRadioButton(devName);
                    rb.setActionCommand(devName);
                    rbPanel.add(rb);
                    rbGroup.add(rb);
                }

                JOptionPane.showMessageDialog(this, rbPanel, JMeterUtils.getLocaleString(SERVER_EMULATOR_CHOOSE_INTERFACE)
                        + " ", JOptionPane.QUESTION_MESSAGE);
                if (rbGroup.getSelection() != null) {
                    listenCaptionLbl.setText(JMeterUtils.getLocaleString(SERVER_EMULATOR_LISTENING_INTERFACE) + " ");
                    String listenDevName = rbGroup.getSelection().getActionCommand();
                    listenDevNameLbl.setText(listenDevName);
                    ipTFByte4End.setEnabled(false);
                    ipTFByte4End.setText("");
                    //Attempts to get listening device IP and fill it into the GUI automatically
                    Enumeration<InetAddress> addresses = null;
                    try {
                        addresses = NetworkInterface.getByName(listenDevName).getInetAddresses();
                    } catch (SocketException e1) {
                        state("error", "Error while reading listening device logical addreses");
                        e1.printStackTrace();
                    }

                    InetAddress addr;
                    byte[] addrBytes = {127, 0, 0, 0};
                    while (addresses.hasMoreElements()) {
                        addr = addresses.nextElement();
                        if (addr instanceof Inet4Address) {
                            addrBytes = addr.getAddress();
                        }
                        //The last IPv4 address found is used
                    }
                    if (addrBytes[0] != 127) {
                        ipTFByte1.setText(String.valueOf(readAsUnsigned(addrBytes[0])));
                        ipTFByte2.setText(String.valueOf(readAsUnsigned(addrBytes[1])));
                        ipTFByte3.setText(String.valueOf(readAsUnsigned(addrBytes[2])));
                        ipTFByte4Start.setText(String.valueOf(readAsUnsigned(addrBytes[3])));
                    } else {
                        state("warn", "Unable to get IPv4 address of the selected listening device. Using IP defined by user via GUI.");
                    }

                    nsConfigured = serverEmulatorCore.configureNs(listenDevNameLbl.getText(), parseIPs().get(0));
                    if (!nsConfigured) {
                        singleMachineCB.setSelected(false);
                    }
                } else {
                    singleMachineCB.setSelected(false); //Launches this action listener again...
                }
            } else {
                if (nsConfigured) {
                    nsConfigured = !serverEmulatorCore.deleteNs(false);
                }
                if (!nsConfigured) {
                    ipTFByte4End.setEnabled(true);
                    listenCaptionLbl.setText("");
                    listenDevNameLbl.setText("");
                }
            }
        }


        else if (source == startDNS) {

            //Vytvoření konfiguračního souboru a přejmenování původního

            //podminka, aby se nepřepsal původní config

            if(DNSpodminka==true) {

                DNSpodminka=false;

                String portDNS = dnsPORT.getText();
                String ip4byte1 = dnsIPbyte1.getText();
                String ip4byte2 = dnsIPbyte2.getText();
                String ip4byte3 = dnsIPbyte3.getText();
                String ip4byte4 = dnsIPbyte4.getText();

                String ip6hextet1 = dnsIPv6Hextet1.getText();
                String ip6hextet2 = dnsIPv6Hextet2.getText();
                String ip6hextet3 = dnsIPv6Hextet3.getText();
                String ip6hextet4 = dnsIPv6Hextet4.getText();
                String ip6hextet5 = dnsIPv6Hextet5.getText();
                String ip6hextet6 = dnsIPv6Hextet6.getText();
                String ip6hextet7 = dnsIPv6Hextet7.getText();
                String ip6hextet8 = dnsIPv6Hextet8.getText();


                String ipv4DNS = ip4byte1 + "." + ip4byte2 + "." + ip4byte3 + "." + ip4byte4;
                String ipv6DNS = ip6hextet1 + ":" + ip6hextet2 + ":" + ip6hextet3 + ":" + ip6hextet4 + ":" + ip6hextet5 + ":" + ip6hextet6 + ":" + ip6hextet7 + ":" + ip6hextet8;

                try {
                    serverEmulatorCore.DNSCreateConfiguration(portDNS, ipv4DNS, ipv6DNS);
                    serverEmulatorCore.DNSCreateZoneDBlocal(ipv4DNS, ipv6DNS );
                    serverEmulatorCore.DNSCreateZoneConfLocal();

                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }

                serverEmulatorCore.restartDNSServer(nsConfigured);
                serverEmulatorCore.getDNSServerStatus(nsConfigured);

            } else {

            }







        }
        else if (source == stopDNS) {

            //podminka, aby se nepřepsal původní config

            if(DNSpodminka==false) {

                DNSpodminka=true;

                //Smazání konfiguračního souborů a vrácení původního
                try {
                    serverEmulatorCore.DNSRestoreConfiguration();
                    serverEmulatorCore.DNSDeleteZoneFiles();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }

                serverEmulatorCore.stopDNSServer(nsConfigured);
                serverEmulatorCore.getDNSServerStatus(nsConfigured);


            } else {
                state("Frstly start DNS using Server Emulator to create new configuration file with DNS Server Configuration");
            }

        }
        else if (source == restartDNS) {
            serverEmulatorCore.restartDNSServer(nsConfigured);
            serverEmulatorCore.getDNSServerStatus(nsConfigured);

        }
        else if (source == dnsStatus) {
            serverEmulatorCore.getDNSServerStatus(nsConfigured);
        }

        else if(source == showIPtoInterface){
            serverEmulatorCore.CommonShowInterface(nsConfigured, commonInterface.getText());
        }
        else if (source == addIPtoInterface){

            String comInterface = commonInterface.getText();

            String commonip4byte1 = commonIPbyte1.getText();
            String commonip4byte2 = commonIPbyte2.getText();
            String commonip4byte3 = commonIPbyte3.getText();
            String commonip4byte4 = commonIPbyte4.getText();

            String commonip6hextet1 = commonIPv6Hextet1.getText();
            String commonip6hextet2 = commonIPv6Hextet2.getText();
            String commonip6hextet3 = commonIPv6Hextet3.getText();
            String commonip6hextet4 = commonIPv6Hextet4.getText();
            String commonip6hextet5 = commonIPv6Hextet5.getText();
            String commonip6hextet6 = commonIPv6Hextet6.getText();
            String commonip6hextet7 = commonIPv6Hextet7.getText();
            String commonip6hextet8 = commonIPv6Hextet8.getText();

            String commonIPv4mask = commonIPv4Mask.getText();
            String commonIPv6mask = commonIPv6Mask.getText();

            if(comInterface.equals("")){
                state("Please insert interface where you want to make changes");
            } else {
                if(commonip4byte1.equals("") && commonip6hextet1.equals("")){
                    state("Please define only IPv4 or IPv6");
                } else{
                    if(!commonip4byte1.equals("") && !commonip6hextet1.equals("")){
                        state("Both fields are defined. Please define only one.");
                    } else{
                        if(!commonip4byte1.equals("")){
                            if(commonip4byte1.equals("")){
                                //Přidání IPv6
                                String FullCommonIPv6 = commonip6hextet1 + "." + commonip6hextet2 + "." + commonip6hextet3 + "." + commonip6hextet4 + "." + commonip6hextet5 + "." + commonip6hextet6 + "." + commonip6hextet7 + "." + commonip6hextet8;
                                serverEmulatorCore.CommonAddInterface(nsConfigured, FullCommonIPv6, commonInterface.getText(), commonIPv6mask);

                            } else {
                                //Přidání IPv4
                                String FullCommonIPv4 = commonip4byte1 + "." + commonip4byte2 + "." + commonip4byte3 + "." + commonip4byte4;
                                serverEmulatorCore.CommonAddInterface(nsConfigured, FullCommonIPv4, commonInterface.getText(), commonIPv4mask);
                            }
                        }
                    }
                }
            }
        }
        else if (source == deleteIPtoInterface){

            String comInterface = commonInterface.getText();

            String commonip4byte1 = commonIPbyte1.getText();
            String commonip4byte2 = commonIPbyte2.getText();
            String commonip4byte3 = commonIPbyte3.getText();
            String commonip4byte4 = commonIPbyte4.getText();

            String commonip6hextet1 = commonIPv6Hextet1.getText();
            String commonip6hextet2 = commonIPv6Hextet2.getText();
            String commonip6hextet3 = commonIPv6Hextet3.getText();
            String commonip6hextet4 = commonIPv6Hextet4.getText();
            String commonip6hextet5 = commonIPv6Hextet5.getText();
            String commonip6hextet6 = commonIPv6Hextet6.getText();
            String commonip6hextet7 = commonIPv6Hextet7.getText();
            String commonip6hextet8 = commonIPv6Hextet8.getText();

            String commonIPv4mask = commonIPv4Mask.getText();
            String commonIPv6mask = commonIPv6Mask.getText();

            if(comInterface.equals("")){
                state("Please insert interface where you want to make changes");
            } else {
                if(commonip4byte1.equals("") && commonip6hextet1.equals("")){
                    state("Please define only IPv4 or IPv6");
                } else{
                    if(!commonip4byte1.equals("") && !commonip6hextet1.equals("")){
                        state("Both IPv4 and IPv are defined. Please define only one.");
                    } else{
                        if(!commonip4byte1.equals("")){
                            if(commonip4byte1.equals("")){
                                //Odstranění IPv6
                                String FullCommonIPv6 = commonip6hextet1 + "." + commonip6hextet2 + "." + commonip6hextet3 + "." + commonip6hextet4 + "." + commonip6hextet5 + "." + commonip6hextet6 + "." + commonip6hextet7 + "." + commonip6hextet8;
                                serverEmulatorCore.CommonDelInterface(nsConfigured, FullCommonIPv6, commonInterface.getText(), commonIPv6mask);

                            } else {
                                //Odstranění IPv4
                                String FullCommonIPv4 = commonip4byte1 + "." + commonip4byte2 + "." + commonip4byte3 + "." + commonip4byte4;
                                serverEmulatorCore.CommonDelInterface(nsConfigured, FullCommonIPv4, commonInterface.getText(), commonIPv4mask);
                            }
                        }
                    }
                }
            }

        }

        else if (source == dhcpStatus) {
            serverEmulatorCore.getDHCPServerStatus(nsConfigured);
        }
        else if (source == startDHCP) {



            if(DHCPpodminka==true){

                DHCPpodminka=false;

                String IPv4interfaces = dhcpIPv4interface.getText();
                String IPv6interfaces = dhcpIPv6interface.getText();

                try {
                    serverEmulatorCore.DHCPstartFunction(IPv4interfaces, IPv6interfaces );
                    serverEmulatorCore.DHCPCreateCommonConfig();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }

                serverEmulatorCore.restartDHCPServer(nsConfigured);
                serverEmulatorCore.getDHCPServerStatus(nsConfigured);
            }




        }
        else if (source == stopDHCP) {
            if(DHCPpodminka==false) {

                DHCPpodminka = true;

                serverEmulatorCore.stopDHCPserver(nsConfigured);

                try {
                    serverEmulatorCore.DHCPstopFunction();
                    serverEmulatorCore.DHCPDeleteCommonConfig();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }

                serverEmulatorCore.getDHCPServerStatus(nsConfigured);
            } else {
            state("Frstly start DHCP using Server Emulator to create new configuration file with DHCP Server Configuration");
        }
        }
        else if (source == restartDHCP) {
        serverEmulatorCore.restartDHCPServer(nsConfigured);
        serverEmulatorCore.getDHCPServerStatus(nsConfigured);
    }

        else if (source== displayUsedPorts){
            serverEmulatorCore.DisplayDHCPports(nsConfigured);
        }
        else if (source == addDHCPport){
            String port = portsDHCP.getText();
            serverEmulatorCore.AddDHCPport(nsConfigured, port);
        }
        else if (source == deleteDHCPport){
            String port = portsDHCP.getText();
            serverEmulatorCore.DeleteDHCPport(nsConfigured, port);
        }
        else if (source == displayDHCPattachedIPs){
            serverEmulatorCore.DisplayDHCPattachedIP(nsConfigured);
        }

        else if(source == startNTP){

            if(NTPpodminka==true) {



            String IPv4maska = NTPmaskIPv4.getText();
            String IPv6maska = NTPmaskIPv6.getText();
            String interfaceNTP = NTPinterface.getText();

            String ip4byte1 = ntpIPbyte1.getText();
            String ip4byte2 = ntpIPbyte2.getText();
            String ip4byte3 = ntpIPbyte3.getText();
            String ip4byte4 = ntpIPbyte4.getText();

            String ip6hextet1 = ntpIPv6Hextet1.getText();
            String ip6hextet2 = ntpIPv6Hextet2.getText();
            String ip6hextet3 = ntpIPv6Hextet3.getText();
            String ip6hextet4 = ntpIPv6Hextet4.getText();
            String ip6hextet5 = ntpIPv6Hextet5.getText();
            String ip6hextet6 = ntpIPv6Hextet6.getText();
            String ip6hextet7 = ntpIPv6Hextet7.getText();
            String ip6hextet8 = ntpIPv6Hextet8.getText();

            String ipv4NTP = ip4byte1 + "." + ip4byte2 + "." + ip4byte3 + "." + ip4byte4;
            String ipv6NTP = ip6hextet1 + ":" + ip6hextet2 + ":" + ip6hextet3 + ":" + ip6hextet4 + ":" + ip6hextet5 + ":" + ip6hextet6 + ":" + ip6hextet7 + ":" + ip6hextet8;

            if(!interfaceNTP.equals("") && (!ip4byte1.equals("") || !ip6hextet1.equals(""))){
                state("Please define only interface, or IP address");
            } else {
                if((!ip4byte1.equals("") && !ip6hextet1.equals("")) || (ip4byte1.equals("") && ip6hextet1.equals("") && interfaceNTP.equals("")) ){
                    state("Please define interface or IPv4 or IPv6");
                } else {
                    if(!ip4byte1.equals("")){
                        //Přiřazení IPv4
                        try {
                            serverEmulatorCore.NTPCreateConfiguration(interfaceNTP, ipv4NTP, IPv4maska );
                            NTPpodminka=false;
                        } catch (IOException ex) {
                            throw new RuntimeException(ex);
                        }

                        serverEmulatorCore.startNTPServer(nsConfigured);
                        serverEmulatorCore.getNTPServerStatus(nsConfigured);

                    } else{
                        //Přiřazení IPv6
                        try {
                            serverEmulatorCore.NTPCreateConfiguration(interfaceNTP, ipv6NTP, IPv6maska );
                            NTPpodminka=false;
                        } catch (IOException ex) {
                            throw new RuntimeException(ex);
                        }

                        serverEmulatorCore.startNTPServer(nsConfigured);
                        serverEmulatorCore.getNTPServerStatus(nsConfigured);
                    }
                }
            }
        }

        }
        else if (source == stopNTP){
            //podminka, aby se nepřepsal původní config

            if(NTPpodminka==false) {

                NTPpodminka=true;
                //Smazání konfiguračního souborů a vrácení původního
                try {
                    serverEmulatorCore.NTPRestoreConfiguration();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }

                serverEmulatorCore.stopNTPServer(nsConfigured);
                serverEmulatorCore.getNTPServerStatus(nsConfigured);

            } else {
                state("Frstly start NTP using Server Emulator to create new configuration file with NTP Server Configuration");
            }
        }
        else if(source == restartNTP){
            serverEmulatorCore.restartNTPServer(nsConfigured);
            serverEmulatorCore.getNTPServerStatus(nsConfigured);
        }
        else if (source == ntpStatus){
            serverEmulatorCore.getNTPServerStatus(nsConfigured);
        }
    }

    /**
     * Reads unsigned value saved in a signed byte variable
     *
     * @param signedVal signed byte variable
     * @return unsigned byte value saved as int
     */
    int readAsUnsigned(byte signedVal) {
        if (signedVal < 0) {
            return 256 + signedVal;
        } else {
            return signedVal;
        }
    }

    /**
     * Sets GUI components for HTTP settings to enabled/disabled
     *
     * @param en - flag indicating if components should be enabled or disabled
     */
    void enableHTTPOptions(boolean en) {
        httpPortTF.setEnabled(en);
        enableSSLCB.setEnabled(en);
        htmlSizeSpinner.setEnabled(en);
        ipTFByte1.setEnabled(en);
        ipTFByte2.setEnabled(en);
        ipTFByte3.setEnabled(en);
        ipTFByte4Start.setEnabled(en);
        ipTFByte4End.setEnabled(en);
        enableAdvancedCB.setEnabled(en);
        if (en) {
            enableAdvancedHTTPOptions(enableAdvancedCB.isSelected());
        } else {
            enableAdvancedHTTPOptions(false);
        }
    }

    /**
     * Sets GUI components for advanced Apache server settings to enabled/disabled
     *
     * @param en - flag indicating if components should be enabled or disabled
     */
    void enableAdvancedHTTPOptions(boolean en) {
        startServersTF.setEnabled(en);
        maxRequestWorkersTF.setEnabled(en);
        threadsPerChildTF.setEnabled(en);
        minSpareThreadsTF.setEnabled(en);
        maxSpareThreadsTF.setEnabled(en);
    }

    /**
     * Uses java.net.NetworkInterface to get a list of active interfaces. It excludes loopback
     * interface.
     *
     * @return a list of valid interfaces
     */
    private List<String> getValidDevNames() {
        List<String> validDevNames = new ArrayList<String>();
        Enumeration<NetworkInterface> nets;
        try {
            nets = NetworkInterface.getNetworkInterfaces();
            for (NetworkInterface netInt : Collections.list(nets)) {
                if (netInt.isUp()) {
                    String netIntName = netInt.getName();
                    if (!netIntName.equals("lo")) {
                        validDevNames.add(netIntName);
                    }
                }
            }
        } catch (SocketException e) {
            state(this, "error", "Error while getting a list of network interfaces:\n" + e.getStackTrace().toString());
        }
        return validDevNames;
    }

    /**
     * Ensures that if user changes spinner value in it's editor directly, it is saved also into the spinner model.
     * Otherwise model.getValue() may differ from editor.getValue() when accessing the value.
     * <p>
     * {@inheritDoc}
     */
    public void stateChanged(ChangeEvent e) {
        if (e.getSource() == htmlSizeSpinner) {
            SpinnerModel model = htmlSizeSpinner.getModel();
            if (model instanceof SpinnerNumberModel) {
                //Following try-catch block ensures that model.getValue does not differ from editor.getValue (in case user changes the value manually)
                try {
                    htmlSizeSpinner.commitEdit();
                } catch (ParseException pe) {
                    // Edited value is invalid, spinner.getValue() will return the last valid value, you could revert the spinner to show that:
                    JComponent editor = htmlSizeSpinner.getEditor();

                    if (editor instanceof DefaultEditor) {
                        ((DefaultEditor) editor).getTextField().setValue(htmlSizeSpinner.getValue());
                        htmlSizeSpinner.setValue(10.0);
                    }
                }
                Number n = (Number) ((SpinnerNumberModel) model).getValue();
                //If user sets the size to 0 then 0.3 as a minimum is set (to allow header in the HTML page)
                if (n.doubleValue() == 0) {
                    htmlSize = 300;
                    htmlSizeSpinner.setValue(0.3);
                } else {
                    htmlSize = n.doubleValue() * 1024; //Conversion of kB to B
                }
            }
        }
    }

    /**
     * Parses values from IP text fields. First it finds out if only a single IP was given. If not it composes a list of addresses based
     * on the range user has set. It also checks if end of range is not lower number than it's start.
     *
     * @return - list of IPs server shall listen on
     */
    ArrayList<String> parseIPs() {
        ArrayList<String> ips = new ArrayList<String>();
        if (ipTFByte4End.getText().equals("")) {
            ips.add(ipTFByte1.getText() + "." + ipTFByte2.getText() + "." + ipTFByte3.getText() + "." + ipTFByte4Start.getText());
        } else {
            int byte4Start = Integer.valueOf(ipTFByte4Start.getText());
            int byte4End = Integer.valueOf(ipTFByte4End.getText());

            if (byte4End <= byte4Start) {
                JOptionPane.showMessageDialog(null, JMeterUtils.getLocaleString(SERVER_EMULATOR_ERROR_IP_RANGE),
                        JMeterUtils.getLocaleString(SERVER_EMULATOR_INVALID_INPUT), JOptionPane.ERROR_MESSAGE);
                ips.add(ipTFByte1.getText() + "." + ipTFByte2.getText() + "." + ipTFByte3.getText() + "." + ipTFByte4Start.getText());
            } else {
                for (int i = byte4Start; i < byte4End + 1; i++) {
                    ips.add(ipTFByte1.getText() + "." + ipTFByte2.getText() + "." + ipTFByte3.getText() + "." + String.valueOf(i));
                }
            }
        }
        return ips;
    }

    /**
     * Manages starting of HTTP server including applying configuration, generating HTML page and configuring network namespace if required
     */


    private void startHTTPServer() {
        if (!isEnabled()) {
            state("warn", "The Server Emulator component is disabled!");
            return;
        }
        if (nsName.length() == 0) {
            state("error", "Loading of configuration was not successful! Aborting!");
            return;
        }
        if (!httpStartedBySE) {
            //Stops the server in case it was started by someone else and maybe with different configuration
            stopHTTPServer(true);
        }
        if (!serverEmulatorCore.isServerRunning(ServerEmulatorCore.HTTP)) {
            boolean success;

            if (enableAdvancedCB.isSelected()) {
                success = serverEmulatorCore.configHTTPServer(parseIPs(), httpPortTF.getText(), enableSSLCB.isSelected(),
                        startServersTF.getText(), maxRequestWorkersTF.getText(), threadsPerChildTF.getText(),
                        minSpareThreadsTF.getText(), maxSpareThreadsTF.getText());
            } else {
                success = serverEmulatorCore.configHTTPServer(parseIPs(), httpPortTF.getText(), enableSSLCB.isSelected());
            }
            if (success) {
                success = serverEmulatorCore.generateHtmlPage(htmlSize);
            }
            if (success) {
                if (!serverEmulatorCore.startHTTPServer(nsConfigured)) {
                    JOptionPane.showMessageDialog(null, JMeterUtils.getLocaleString(SERVER_EMULATOR_ERROR_SHUTDOWN),
                            JMeterUtils.getLocaleString(SERVER_EMULATOR_ERROR), JOptionPane.ERROR_MESSAGE);
                    StandardJMeterEngine.stopEngine();
                } else {
                    httpStartedBySE = true;
                }
            }

        } else {
            state("The HTTP server has already been running");
        }
    }

    /**
     * Manages stopping of HTTP server including deletion of network namespace if it was used and FTP is not running in it
     */


    private void stopHTTPServer(boolean silent) {
        if (!isEnabled()) {
            state("warn", "The Server Emulator component is disabled!");
            return;
        }
        if (nsName.length() == 0) {
            state("error", "Loading of configuration was not successful! Aborting!");
            return;
        }
        if (serverEmulatorCore.isServerRunning(ServerEmulatorCore.HTTP)) {
            serverEmulatorCore.stopHTTPServer(nsConfigured);
            httpStartedBySE = false;
        } else {
            if (!silent) {
                state("The HTTP server had not been running");
            }
        }
    }

    /**
     * Manages starting of FTP server including configuration of network namespace if required
     */
    private void startFTPServer() {
        if (!isEnabled()) {
            state("warn", "The Server Emulator component is disabled!");
            return;
        }
        if (nsName.length() == 0) {
            state("error", "Loading of configuration was not successful! Aborting!");
            return;
        }
        if (!dnsStartedBySE) {
            //Stops the server in case it was started by someone else and maybe with different configuration
            stopFTPServer(true);
        }
        if (!serverEmulatorCore.isServerRunning(ServerEmulatorCore.FTP)) {

            if (!serverEmulatorCore.startFTPServer(nsConfigured)) {
                JOptionPane.showMessageDialog(null, JMeterUtils.getLocaleString(SERVER_EMULATOR_ERROR_SHUTDOWN),
                        JMeterUtils.getLocaleString(SERVER_EMULATOR_ERROR), JOptionPane.ERROR_MESSAGE);
                StandardJMeterEngine.stopEngine();
            } else {
                ftpStartedBySE = true;
            }
        } else {
            state("The FTP server has already been running");
        }
    }

    /**
     * Manages stopping of FTP server including deletion of network namespace if it was used and HTTP is not running in it
     */
    private void stopFTPServer(boolean silent) {
        if (!isEnabled()) {
            state("warn", "The Server Emulator component is disabled!");
            return;
        }
        if (nsName.length() == 0) {
            state("error", "Loading of configuration was not successful! Aborting!");
            return;
        }
        if (serverEmulatorCore.isServerRunning(ServerEmulatorCore.FTP)) {
            serverEmulatorCore.stopFTPServer(nsConfigured);
            ftpStartedBySE = false;
        } else {
            if (!silent) {
                state("The FTP server had not been running");
            }
        }
    }

    /**
     * Registers a listener which reacts to events of start/end of the test.
     * This is necessary because simple implementation of JMeter TestStateListener interface does not work for JMeter GUI classes
     */
    private void registerTestStateListener() {
        TestStateListener testStateListener = new TestStateListener() {

            @Override
            public void testStarted() {
                if (httpAutoStartCB.isSelected()) {
                    startHTTPServer();
                }
                if (ftpAutoStartCB.isSelected()) {
                    startFTPServer();
                }
            }

            @Override
            public void testStarted(String host) {
                testStarted();
            }

            @Override
            public void testEnded() {
                //Register again for a next run
                registerTestStateListener();

                if (httpAutoStartCB.isSelected()) {
                    stopHTTPServer(false);
                }
                if (ftpAutoStartCB.isSelected()) {
                    stopFTPServer(false);
                }
            }

            @Override
            public void testEnded(String host) {
                testEnded();
            }
        };
        StandardJMeterEngine.register(testStateListener);
    }

    /**
     * Attaches pre-listener to catch an "exit" event = before closing JMeter, to perform cleanup
     */
    private void addExitListener() {
        ActionRouter.getInstance().addPreActionListener(ExitCommand.class, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (httpStartedBySE) {
                    stopHTTPServer(true);
                }

                if (ftpStartedBySE) {
                    stopFTPServer(true);
                }

                if (serverEmulatorCore.isListenersRegistered()) { //Checks if the core was really used at all
                    serverEmulatorCore.deleteNs(true);
                }

                // Vrácení původního config souboru s DNS konfigurací
                if(DNSpodminka==false){

                    try {
                        serverEmulatorCore.DNSRestoreConfiguration();
                        serverEmulatorCore.DNSDeleteZoneFiles();
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                }

                serverEmulatorCore.restartDNSServer(nsConfigured);

                if(DHCPpodminka==false){

                    try {
                        serverEmulatorCore.DHCPstopFunction();
                        serverEmulatorCore.DHCPDeleteCommonConfig();
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                }

                serverEmulatorCore.restartDHCPServer(nsConfigured);

                if(NTPpodminka==false){
                    try {
                        serverEmulatorCore.NTPRestoreConfiguration();
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                }
                serverEmulatorCore.restartNTPServer(nsConfigured);

            }
        });
    }


}
