import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import CardConnect.AddonFunctions;
import com.jcraft.jsch.JSchException;
import com.pastdev.jsch.DefaultSessionFactory;
import com.pastdev.jsch.command.CommandRunner;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;

public class RegisterTC extends JDialog{
    private JTextField tfIP;
    private JTextField tfPass;
    private JButton btnLogin;
    private JTextField tfID;
    private JButton btnSend;
    private JPanel registerPanel;
    private JTextField tfName;
    private JPasswordField pfPassword;
    private JTextField tfDescription;
    private JLabel mark;
    private JButton cancelButton;

    public RegisterTC(JFrame parent) {
        super(parent);
        setTitle("Create a new account");
        setContentPane(registerPanel);
        setMinimumSize(new Dimension(500, 500));
        setModal(true);
        setLocationRelativeTo(parent);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        mark.setVisible(false);

        btnLogin.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    sshRaspberry(1);
                } catch (NoSuchPaddingException ex) {
                    ex.printStackTrace();
                } catch (IllegalBlockSizeException ex) {
                    ex.printStackTrace();
                } catch (NoSuchAlgorithmException ex) {
                    ex.printStackTrace();
                } catch (IOException ex) {
                    ex.printStackTrace();
                } catch (BadPaddingException ex) {
                    ex.printStackTrace();
                } catch (InvalidKeyException ex) {
                    ex.printStackTrace();
                }
            }
        });
        btnSend.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    sshRaspberry(2);
                } catch (NoSuchPaddingException ex) {
                    ex.printStackTrace();
                } catch (IllegalBlockSizeException ex) {
                    ex.printStackTrace();
                } catch (NoSuchAlgorithmException ex) {
                    ex.printStackTrace();
                } catch (IOException ex) {
                    ex.printStackTrace();
                } catch (BadPaddingException ex) {
                    ex.printStackTrace();
                } catch (InvalidKeyException ex) {
                    ex.printStackTrace();
                }
            }
        });
        cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });
        setVisible(true);
    }

    private void sshRaspberry(int choose) throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, IOException, BadPaddingException, InvalidKeyException {

        String IP = tfIP.getText();
        String name = tfName.getText();
        String password = String.valueOf(pfPassword.getPassword());
        String ID = tfID.getText();
        String description = tfDescription.getText();
        String command;


        if (IP.isEmpty() || name.isEmpty()|| password.isEmpty()) {
            JOptionPane.showMessageDialog(this,
                    "Please enter all fields",
                    "Try again",
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
        else {

            DefaultSessionFactory sessionFactory = new DefaultSessionFactory(
                    name, IP, 22
            );

            Map props = new HashMap<String, String>();
            props.put("StrictHostKeyChecking", "no");
            sessionFactory.setConfig(props);
            sessionFactory.setPassword(password);

            CommandRunner runner = new CommandRunner(sessionFactory);

            if(choose == 1){
            command = "cd /home/pi && ./aut_protocol -i";
            }
            else{
                if (ID.isEmpty()) {
                    JOptionPane.showMessageDialog(this,
                            "Please use Login button",
                            "Try again",
                            JOptionPane.ERROR_MESSAGE);
                    return;
                }
                boolean tc = trustcoreExists(ID);
                if (tc) {
                    JOptionPane.showMessageDialog(this,
                            "Trustcore is already registered!",
                            "Error",
                            JOptionPane.ERROR_MESSAGE);
                    return;
                }
                if (description.isEmpty()) {
                    JOptionPane.showMessageDialog(this,
                            "Please write some to description",
                            "Try again",
                            JOptionPane.ERROR_MESSAGE);
                    return;
                }
                System.out.println("Generates new Trust Core private key");
                long time_a = System.nanoTime();
                String passwordTc = AddonFunctions.genVerifierKey(ID);
                long time_b = System.nanoTime();
                System.out.println("New trust Core private key was generated");
                System.out.println("It took " + (new Long(time_b - time_a))+
                        " nanoseconds.\n");

                trustcore = addTrustcoreToDatabase(IP, name, password, ID, passwordTc, description);
                if (trustcore != null) {
                    //dispose();
                }
                else {
                    JOptionPane.showMessageDialog(this,
                            "Failed to register new trustcore",
                            "Try again",
                            JOptionPane.ERROR_MESSAGE);
                    return;
                }

                //System.out.println(": "+passwordTc);
                command = "cd /home/pi && ./aut_protocol -u "+ passwordTc;
                //return;
            }

            CommandRunner.ExecuteResult result = null;
            long time_a = System.nanoTime();
            try {
                result = runner.execute(command);
            } catch (JSchException ex) {
                ex.printStackTrace();
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            if (result.getStderr().isEmpty()) {
                System.out.println(result.getStdout());
                if(choose == 1) {
                    ID = result.getStdout();
                    tfID.setText(ID);
                }
                if(result.getStdout().equals("Trust Core private key was updated successfully")){
                    mark.setVisible(true);
                    long time_b = System.nanoTime();
                    System.out.println("It took " + (new Long(time_b - time_a)/1000000) +
                            " milliseconds.\n");
                }
            } else {
                System.out.println(result.getStderr());
            }

            try {
                runner.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

    }

    private boolean trustcoreExists(String ID) {
        //Trustcore trustcore = null;
        final String DB_URL = "jdbc:mysql://localhost/CardDatabase?serverTimezone=UTC";
        final String USERNAME = "root";
        final String PASSWORD = "";

        try{
            Connection conn = DriverManager.getConnection(DB_URL, USERNAME, PASSWORD);
            // Connected to database successfully...

            String sqlSelectCard = "SELECT * FROM trustcore WHERE id = '"+ ID +"'";
            Statement stmt = conn.createStatement();
            ResultSet resultSet = stmt.executeQuery(sqlSelectCard);

            //ResultSet resultSet = stmt.executeQuery("SELECT id FROM users WHERE id= "+ID);

           if (resultSet.next()) {
                return true;
            }

            stmt.close();
            conn.close();
        }catch(Exception e){
            e.printStackTrace();
        }

        return false;
    }

    public Trustcore trustcore;
    private Trustcore addTrustcoreToDatabase(String IP,String name, String password, String ID, String keyTC, String description) {
        Trustcore trustcore = null;
        final String DB_URL = "jdbc:mysql://localhost/CardDatabase?serverTimezone=UTC";
        final String USERNAME = "root";
        final String PASSWORD = "";

        try{
            Connection conn = DriverManager.getConnection(DB_URL, USERNAME, PASSWORD);
            // Connected to database successfully...

            Statement stmt = conn.createStatement();
            String sql = "INSERT INTO trustcore (id, ip, nameLogin, passwordLogin, keyTC, description) " +
                    "VALUES (?, ?, ?, ?, ?, ?)";
            PreparedStatement preparedStatement = conn.prepareStatement(sql);
            preparedStatement.setString(1, ID);
            preparedStatement.setString(2, IP);
            preparedStatement.setString(3, name);
            preparedStatement.setString(4, password);
            preparedStatement.setString(5, keyTC);
            preparedStatement.setString(6, description);

            //Insert row into the table
            int addedRows = preparedStatement.executeUpdate();
            if (addedRows > 0) {
                trustcore = new Trustcore();
                trustcore.ID = ID;
                trustcore.IP = IP;
                trustcore.name = name;
                trustcore.password = password;
                trustcore.keyTC = keyTC;
                trustcore.description = description;
            }

            stmt.close();
            conn.close();
        }catch(Exception e){
            e.printStackTrace();
        }

        return trustcore;
    }

    public static void main(String[] args) {
        RegisterTC myForm = new RegisterTC(null);
        Trustcore trustcore = myForm.trustcore;
        if (trustcore != null) {
            System.out.println("Successful registration of: " + trustcore.name);
        } else {
            System.out.println("Registration canceled");
        }
    }
}
