package jguard.client.gui.dialog;

import cucky.jGuard.lib.LogComparator;
import cucky.jGuard.lib.LogFile;
import cucky.jGuard.lib.Message;
import cucky.jGuard.lib.Status;
import cucky.jGuard.lib.object.Log;
import cucky.jGuard.lib.object.MapObject;
import cucky.jGuard.lib.object.ObjectServices;
import cucky.jGuard.lib.object.ObjectType;
import cucky.jGuard.lib.object.SnmpProbe;
import cucky.jGuard.lib.object.SnmpProfile;
import cucky.jGuard.snmp.SNMPManager;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import jguard.client.Client;
import org.snmp4j.smi.OID;

public class ObjectDialog extends JDialog {

    private MapObject obj;
    private Boolean newObject;

    private JTextField nazevText = new JTextField();
    private JLabel nazevWarning = new JLabel("Název musi mit min. 3 znaky");
    private JTextField ipText = new JTextField();
    private JLabel ipWarning = new JLabel("Neplatná IP adresa");
    private JComboBox<String> typeComboBox = new JComboBox<String>();
    private JTextField userText = new JTextField();
    private JPasswordField hesloText = new JPasswordField();
    private DefaultComboBoxModel<String> snmpmodel = new DefaultComboBoxModel<String>();
    private JCheckBox disableCheBox = new JCheckBox();
    private JTextField locationText = new JTextField();
    private JTextArea descriptionText = new JTextArea();

    private JCheckBox winboxBox = new JCheckBox("Winbox");
    private JTextField portWinbox = new JTextField("8291");
    private JCheckBox sshBox = new JCheckBox("SSH");
    private JTextField portSsh = new JTextField("22");
    private JCheckBox wwwBox = new JCheckBox("Web");
    private JTextField portWww = new JTextField("80");
    private JComboBox<String> wwwVerzeComboBox = new JComboBox<String>();
    private JCheckBox telnetBox = new JCheckBox("Telnet");
    private JTextField portTelnet = new JTextField("23");
    private JCheckBox smstBox = new JCheckBox("SMS");
    private JTextField portSms = new JTextField("5020");
    private JComboBox<String> smsVerzeComboBox = new JComboBox<String>();
    private JComboBox<String> snmpProfileComboBox = new JComboBox<String>();

    public ObjectDialog(MapObject obj, boolean newObject) {

        this.obj = obj;
        this.newObject = newObject;

        setTitle("Vlastnosti objektu");
        setSize(600, 520);
        setLocationRelativeTo(null);
        setVisible(true);
        setAlwaysOnTop(true);
        
        setLayout(new BorderLayout());

        JTabbedPane tabbedPane = new JTabbedPane();

        JScrollPane tabNastaveni = new JScrollPane(tabNastaveni(),
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        tabbedPane.addTab("Informace", tabInfo());
        tabbedPane.addTab("Nastaveni", tabNastaveni);
        tabbedPane.addTab("Služby", tabSluzby());
        tabbedPane.addTab("Události", tabUdalosti());
        tabbedPane.addTab("Sondy", tabSondy());
        
        // pokud se jedna o novy objekt 
        if (newObject) { 
            tabbedPane.setSelectedIndex(1); // prepne na kartu nastaveni
            tabbedPane.setEnabledAt(0, false); // vypne kartu informace
            tabbedPane.setEnabledAt(3, false); // vypne kartu udalosti
        }
        
        add(tabbedPane, BorderLayout.CENTER);

        JPanel pane = new JPanel();
        JButton save = new JButton("Ulozit");
        save.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // kontrola chyb
                if (nazevText.getText().length() < 3) {
                    nazevWarning.setVisible(true);
                    return;
                }
                nazevWarning.setVisible(false);
                if (!validateIp(ipText.getText())) {
                    ipWarning.setVisible(true);
                    return;
                }
                ipWarning.setVisible(false);
                // ulozeni do objektu
                obj.setName(nazevText.getText());
                obj.setIp(ipText.getText());
                obj.setUser(userText.getText());
                obj.setPassword(new String(hesloText.getPassword()));
                for (int i = 0; i < Client.deviceType.size(); i++) {
                    if (typeComboBox.getSelectedIndex() == i) {
                        obj.setType(Client.deviceType.get(i).getId());
                    }
                }
                obj.setSnmpProfile(Client.serverSettings.getSnmp().get(snmpProfileComboBox.getSelectedIndex()).getId());
                obj.setActive(disableCheBox.isSelected());
                obj.setDescription(descriptionText.getText());
                obj.setLocation(locationText.getText());

                ObjectServices service = new ObjectServices();
                service.setWinbox(winboxBox.isSelected());
                service.setPortWinbox(portWinbox.getText());
                service.setSsh(sshBox.isSelected());
                service.setPortSsh(portSsh.getText());
                service.setWeb(wwwBox.isSelected());
                service.setPortWeb(portWww.getText());
                service.setVerzeWeb(wwwVerzeComboBox.getSelectedIndex());
                service.setTelnet(telnetBox.isSelected());
                service.setPortTelnet(portTelnet.getText());
                service.setSms(smstBox.isSelected());
                service.setPortSms(portSms.getText());
                service.setVerzeSms(smsVerzeComboBox.getSelectedIndex());
                obj.setService(service);

                ArrayList<SnmpProbe> probe = new ArrayList<>();
                if (!newObject) {
                    probe.addAll(obj.getSnmpProbe());
                }
                obj.setSnmpProbe(probe);

                if (newObject) {
                    Client.client.send(Message.ADD_OBJECT, obj);
                } else {
                    Client.client.send(Message.UPDATE_OBJECT, obj);
                }

                // zavreni dialogu
                dispose();
            }
        });
        pane.add(save);

        JButton cancel = new JButton("Zrusit");
        cancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });
        pane.add(cancel);

        add(pane, BorderLayout.PAGE_END);

        

        // nacteni snmp profilu
        for (SnmpProfile sp : Client.serverSettings.getSnmp()) {
            snmpmodel.addElement(sp.getName());
        }

        // doplneni poli dialogu podle vybraneho objektu
        if (!newObject) {
            nazevText.setText(obj.getName());
            ipText.setText(obj.getIp());
            userText.setText(obj.getUser());
            hesloText.setText(obj.getPassword());
            for (int i = 0; i < Client.deviceType.size(); i++) {
                if (obj.getType() == Client.deviceType.get(i).getId()) {
                    typeComboBox.setSelectedIndex(i);
                }
            }
            
            for (int i = 0; i < Client.serverSettings.getSnmp().size(); i++) {
                if (Client.serverSettings.getSnmp().get(i).getId() == obj.getSnmpProfile()) {
                    snmpProfileComboBox.setSelectedIndex(i);
                }
            }
            disableCheBox.setSelected(obj.isActive());
            descriptionText.setText(obj.getDescription());
            locationText.setText(obj.getLocation());
            winboxBox.setSelected(obj.getService().isWinbox());
            portWinbox.setText(String.valueOf(obj.getService().getPortWinbox()));
            sshBox.setSelected(obj.getService().isSsh());
            portSsh.setText(String.valueOf(obj.getService().getPortSsh()));
            wwwBox.setSelected(obj.getService().isWeb());
            portWww.setText(String.valueOf(obj.getService().getPortWeb()));
            wwwVerzeComboBox.setSelectedIndex(obj.getService().getVerzeWeb());
            telnetBox.setSelected(obj.getService().isTelnet());
            portTelnet.setText(String.valueOf(obj.getService().getPortTelnet()));
            smstBox.setSelected(obj.getService().isSms());
            portSms.setText(String.valueOf(obj.getService().getPortSms()));
            smsVerzeComboBox.setSelectedIndex(obj.getService().getVerzeSms());
        } else {
            disableCheBox.setSelected(true);
        }

    }

    private JPanel tabInfo() {
        JPanel p = new JPanel(null);

        Map<String, String> label = new HashMap<String, String>();
        label.put("Popis", "1.3.6.1.2.1.1.1.0");
        label.put("Uptime", "1.3.6.1.2.1.1.3.0");
        label.put("Contact", "1.3.6.1.2.1.1.4.0");
        label.put("Name", "1.3.6.1.2.1.1.5.0");

        if(!newObject){ /// TODO u objektu u kterych neni snmp protokol povolen vraci system err null
            Thread ti = new Thread() {
                @Override
                public void run() {
                    super.run();
                    // nacteni snmp profilu
                    String port = "161";
                    String community = "public";
                    int version = SNMPManager.version1;
                    for (SnmpProfile sp : Client.serverSettings.getSnmp()) {
                        if (obj.getSnmpProfile() == sp.getId()) {
                            port = sp.getPort();
                            community = sp.getCommunity();
                            version = sp.getVersion();
                            break;
                        }
                    }
                    SNMPManager mngr = new SNMPManager(obj.getIp(), port, community, version);
                    try {
                        mngr.start();

                    } catch (Exception e) {
                    }
                    int y = 30;
                    for (Entry<String, String> entry : label.entrySet()) {
                        try {
                            JLabel label = new JLabel(entry.getKey());
                            label.setBounds(20, y, 90, 25);
                            JLabel value = new JLabel(mngr.getAsString(new OID(entry.getValue())));
                            value.setBounds(100, y, 200, 25);
                            p.add(label);
                            p.add(value);
                            y += 30;
                            p.revalidate();
                            p.repaint();
                        } catch (Exception e) {
                            LogFile.printErr("Object dialog - SNMP error: " + e);
                        }
                    }
                }
            };
            ti.start();
        }
        return p;
    }

    private JPanel tabNastaveni() {
        JPanel p = new JPanel();

        p.setLayout(null);

        JLabel nazevLabel = new JLabel("Název");
        nazevLabel.setBounds(20, 30, 80, 25);
        p.add(nazevLabel);

        nazevText.setBounds(110, 30, 160, 25);
        p.add(nazevText);
        nazevWarning.setForeground(Color.red);
        nazevWarning.setBounds(110, 55, 160, 25);
        nazevWarning.setVisible(false);
        p.add(nazevWarning);

        JLabel ipLabel = new JLabel("IP adresa");
        ipLabel.setBounds(300, 30, 80, 25);
        p.add(ipLabel);

        ipText.setBounds(390, 30, 160, 25);
        p.add(ipText);
        ipWarning.setForeground(Color.red);
        ipWarning.setBounds(390, 55, 160, 25);
        ipWarning.setVisible(false);
        p.add(ipWarning);

        JLabel typLabel = new JLabel("Typ");
        typLabel.setBounds(20, 130, 80, 25);
        p.add(typLabel);

        DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>();
        for (ObjectType obj : Client.deviceType) {
            model.addElement(obj.getName());
        }

        typeComboBox.setModel(model);
        typeComboBox.setBounds(110, 130, 160, 25);
        p.add(typeComboBox);

        JLabel userLabel = new JLabel("Uživatel");
        userLabel.setBounds(20, 80, 80, 25);
        p.add(userLabel);

        userText.setBounds(110, 80, 160, 25);
        p.add(userText);

        JLabel hesloLabel = new JLabel("Heslo");
        hesloLabel.setBounds(300, 80, 80, 25);
        p.add(hesloLabel);

        hesloText.setBounds(390, 80, 160, 25);
        p.add(hesloText);

        JLabel snmpLabel = new JLabel("SNMP profil");
        snmpLabel.setBounds(300, 130, 80, 25);
        p.add(snmpLabel);

        snmpProfileComboBox.setModel(snmpmodel);
        snmpProfileComboBox.setBounds(390, 130, 160, 25);
        p.add(snmpProfileComboBox);

        JLabel disableLabel = new JLabel("Aktivní");
        disableLabel.setBounds(20, 180, 80, 25);
        p.add(disableLabel);

        disableCheBox.setBounds(110, 180, 160, 25);
        p.add(disableCheBox);

        JButton snmpTest = new JButton("Test SNMP");
        snmpTest.setBounds(390, 180, 160, 25);
        snmpTest.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                /* TODO
                Thread testSnmp = new Thread() {
                    @Override
                    public void run() {

                        try {
                            // nacteni snmp profilu
                            String port = "161";
                            String community = "public";
                            int version = SNMPManager.version1;
                            for (int i = 0; i < Client.serverSettings.getSnmp().size(); i++) {
                                if (snmpProfileComboBox.getSelectedIndex() == i) {
                                    port = Client.serverSettings.getSnmp().get(i).getPort();
                                    community = Client.serverSettings.getSnmp().get(i).getCommunity();
                                    version = Client.serverSettings.getSnmp().get(i).getVersion();
                                    break;
                                }
                            }
                            SNMPManager mngr = new SNMPManager(ipText.getText(), port, community, version);
                            mngr.start();
                            String desc = mngr.getSysDescr();
                            JOptionPane.showMessageDialog(ObjectDialog.this, "Odpoved: " + desc, "SNMP test", JOptionPane.INFORMATION_MESSAGE);
                        } catch (Exception ex) {
                            JOptionPane.showMessageDialog(ObjectDialog.this, "SNMP se nepodařilo načíst", "SNMP test", JOptionPane.ERROR_MESSAGE);
                            System.err.println("SNMP test error: " + ex.getMessage());
                        }

                    }
                };
                testSnmp.start();
                */
            }
        });
        p.add(snmpTest);

        JLabel locLabel = new JLabel("Umístění");
        locLabel.setBounds(20, 230, 80, 25);
        p.add(locLabel);

        locationText.setBounds(110, 230, 440, 25);
        p.add(locationText);

        JLabel descLabel = new JLabel("Poznámka");
        descLabel.setBounds(20, 280, 80, 25);
        p.add(descLabel);

        descriptionText.setBounds(110, 280, 440, 100);
        descriptionText.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.BLACK), BorderFactory.createEmptyBorder(10, 10, 10, 10)));
        p.add(descriptionText);
       
        return p;
    }

    private JPanel tabSluzby() {
        JPanel p = new JPanel();

        p.setLayout(null);
        
        winboxBox.setBounds(20, 30, 80, 25);
        p.add(winboxBox);

        JLabel winbox_port = new JLabel("port:");
        winbox_port.setBounds(130, 30, 60, 25);
        p.add(winbox_port);

        portWinbox.setBounds(180, 30, 60, 25);
        p.add(portWinbox);
         
        sshBox.setBounds(20, 60, 80, 25);
        p.add(sshBox);

        JLabel ssh_port = new JLabel("port:");
        ssh_port.setBounds(130, 60, 60, 25);
        p.add(ssh_port);

        portSsh.setBounds(180, 60, 60, 25);
        p.add(portSsh);

        wwwBox.setBounds(20, 90, 80, 25);
        p.add(wwwBox);

        JLabel www_port = new JLabel("port:");
        www_port.setBounds(130, 90, 60, 25);
        p.add(www_port);

        portWww.setBounds(180, 90, 60, 25);
        p.add(portWww);

        JLabel www_verze = new JLabel("verze:");
        www_verze.setBounds(260, 90, 60, 25);
        p.add(www_verze);

        wwwVerzeComboBox.setModel(new DefaultComboBoxModel(new String[]{"HTTP", "HTTPS"}));
        wwwVerzeComboBox.setBounds(320, 90, 80, 25);
        p.add(wwwVerzeComboBox);

        telnetBox.setBounds(20, 120, 80, 25);
        p.add(telnetBox);

        JLabel telnet_port = new JLabel("port:");
        telnet_port.setBounds(130, 120, 60, 25);
        p.add(telnet_port);

        portTelnet.setBounds(180, 120, 60, 25);
        p.add(portTelnet);

        smstBox.setBounds(20, 150, 80, 25);
        p.add(smstBox);

        JLabel sms_port = new JLabel("port:");
        sms_port.setBounds(130, 150, 60, 25);
        p.add(sms_port);

        portSms.setBounds(180, 150, 60, 25);
        p.add(portSms);

        JLabel sms_verze = new JLabel("verze:");
        sms_verze.setBounds(260, 150, 60, 25);
        p.add(sms_verze);

        smsVerzeComboBox.setModel(new DefaultComboBoxModel(new String[]{"SDV", "BT"}));
        smsVerzeComboBox.setBounds(320, 150, 80, 25);
        p.add(smsVerzeComboBox);

        return p;
    }

    private JScrollPane tabUdalosti() {

        String column[] = {"Začátek", "Konec", "Stav"};
        DefaultTableModel tableModel = new DefaultTableModel(column, 0) {

            @Override
            public boolean isCellEditable(int row, int column) {
                //all cells false
                return false;
            }
        };

        try {
            // TODO pri vytvareni noveho objektu to vyhodi chybu
            Collections.sort(Client.log, new LogComparator());
            Collections.reverse(Client.log);
            if (!newObject) {
                for (Log l : Client.log) {
                    if (l.getDevice() == obj.getId()) {
                        Object[] d = {
                            getDate(l.getFrom()),
                            getDate(l.getTo()),
                            getStatus(l.getStatus())};
                        tableModel.addRow(d);
                    }

                }
            }
            
        } catch (Exception e) {
            LogFile.printErr("Object log error: " + e.getMessage());
        }
        JTable table = new JTable(tableModel);

        return new JScrollPane(table);
    }

    private JPanel tabSondy() {
        JPanel panel = new JPanel();

        panel.setLayout(new BorderLayout());

        String column[] = {"Popis", "OID", "Aktivni", "Zobrazit"};
        DefaultTableModel tableModel = new DefaultTableModel(column, 0);
        if (!newObject) {
            try {
                for (SnmpProbe p : obj.getSnmpProbe()) {
                    Object[] d = {p.getName(), p.getOid(), "", ""};
                    tableModel.addRow(d);
                }
            } catch (Exception e) {
                LogFile.printErr("Probe list " + e.getMessage());
            }
        }
        
        JScrollPane table = new JScrollPane();
        table.add(new JTable(tableModel));
        panel.add(new JTable(tableModel), BorderLayout.CENTER);

        JPanel jp = new JPanel();
        jp.add(new JLabel("Přidat: "));
        panel.add(jp, BorderLayout.PAGE_END);
         
        return panel;
    }

    public boolean validateIp(String ip) {
        Pattern pattern = Pattern.compile("^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
        Matcher matcher = pattern.matcher(ip);
        return matcher.matches();
    }

    public boolean validatePort(String port) {
        try {
            int pNum = Integer.parseInt(port);
            if ((pNum > 0) && (pNum < 65536)) {
                return true;
            }
        } catch (NumberFormatException e) {
        }
        return false;
    }

    private String getDate(long date) {
        if (date != 0) {
            SimpleDateFormat ft = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
            return ft.format(new Date(date));
        }
        return "";
    }

    private String getStatus(int status) {
        switch (status) {
            case Status.OK: // online
                return "online";
            case Status.WARNING: // warning
                return "varování";
            case Status.OFFLINE: // offline
                return "offline";
            default: // other
                return "n/a";
        }
    }

}
