package ggh.dialog;

import flanagan.math.Matrix;
import ggh.GGHData;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

/**
 *
 * @author Admin
 */
public class Dialog2_Encrypt extends JPanel {
    private javax.swing.ButtonGroup connectorGroup;
    private javax.swing.JCheckBox jCheckBox1;

    private JPanel contentPanel;
    private JLabel textLabel;
    private JPanel titlePanel;

    private JButton m_sampleButton = new JButton("Vložit vzor");
    private JButton e_vectorButton = new JButton("<html>Vypočítat zašifrovaný vektor<p><b>e</b> = <b>m</b>W + <b>r</b></p></html>");
    private JButton r_sampleButton = new JButton("Vložit vzor");

    private JTextField[] m_data = new JTextField[5];
    private JTextField[] e_data = new JTextField[5];
    private JTextField[] r_data = new JTextField[5];

    public Dialog2_Encrypt() {

        super();

        contentPanel = getContentPanel();
        contentPanel.setBorder(new EmptyBorder(new Insets(10, 10, 10, 10)));

    

        titlePanel = new javax.swing.JPanel();
        textLabel = new javax.swing.JLabel();
        
        setLayout(new java.awt.BorderLayout());


        titlePanel.setLayout(new java.awt.BorderLayout());
        titlePanel.setBackground(Color.gray);

        textLabel.setBackground(Color.lightGray);
        textLabel.setFont(new Font("MS Sans Serif", Font.BOLD, 15));
        textLabel.setText("2. Šifrování");
        textLabel.setBorder(new EmptyBorder(new Insets(10, 10, 10, 10)));
        textLabel.setOpaque(true);

        titlePanel.add(textLabel, BorderLayout.CENTER);
      
        add(titlePanel, BorderLayout.NORTH);
        JPanel secondaryPanel = new JPanel(new BorderLayout());
        secondaryPanel.add(contentPanel, BorderLayout.NORTH);
        add(secondaryPanel, BorderLayout.CENTER);

    }

    public void addCheckBoxActionListener(ActionListener l) {
        jCheckBox1.addActionListener(l);
    }

    public boolean isCheckBoxSelected() {
        return jCheckBox1.isSelected();
    }

    public String getRadioButtonSelected() {
        return connectorGroup.getSelection().getActionCommand();
    }

    private JPanel getContentPanel() {
        JPanel contentPanel1 = new JPanel(new GridLayout(4, 0, 5, 0));

        JPanel m_vectorBorder = new JPanel(new BorderLayout(5,0));
        m_vectorBorder.setBorder(BorderFactory.createTitledBorder("Volba vektoru m určeného k zašifrování"));
        JPanel m_vector = new JPanel(new GridLayout(1,1,5,0));
    
        m_vectorBorder.add(m_vector, BorderLayout.WEST);

        m_vector.add(new JLabel("<html><b>m</b><sub>", JLabel.LEFT));
        for (int i = 0; i < GGHData.MAX_DIMENSION; i++) {

            m_data[i] = new JTextField(12);
            m_vector.add(m_data[i]);
        }
        
        m_vectorBorder.add(m_sampleButton, BorderLayout.EAST);

        
        JPanel r_vectorBorder = new JPanel(new BorderLayout(5,0));
        r_vectorBorder.setBorder(BorderFactory.createTitledBorder("Volba malého náhodného vektoru r nutného pro šifrování"));
        JPanel r_vector = new JPanel(new GridLayout(1,1,5,0));

        r_vectorBorder.add(r_vector, BorderLayout.WEST);

        r_vector.add(new JLabel("<html><b>r</b><sub>", JLabel.LEFT));
        for (int i = 0; i < GGHData.MAX_DIMENSION; i++) {

            r_data[i] = new JTextField(12);
            r_vector.add(r_data[i]);
        }
        

        r_vectorBorder.add(r_sampleButton, BorderLayout.EAST);


        JPanel e_vectorBorder = new JPanel(new BorderLayout(10,0));
        e_vectorBorder.setBorder(BorderFactory.createTitledBorder("Výpočet zašifrovaného vektoru e = mW + r"));
        JPanel e_vector = new JPanel(new GridLayout(1,0,5,0));

        e_vectorBorder.add(e_vector, BorderLayout.WEST);

        e_vector.add(new JLabel("<html><b>e</b><sub>", JLabel.LEFT));
        for (int i = 0; i < GGHData.MAX_DIMENSION; i++) {

            e_data[i] = new JTextField(12);
            e_vector.add(e_data[i]);
        }


        e_vectorBorder.add(e_vectorButton, BorderLayout.EAST);

        JPanel text_border = new JPanel(new GridLayout(1,0,0,0));
        text_border.setBorder(BorderFactory.createTitledBorder("Teoretický popis šifrovací metody GGH"));

        JLabel jText1 = new JLabel("<html>Alice si vybere docela vzájemně ortogonální množinu lineárně nezávislých vektorů <b>v</b><sub>1</sub>, ..., <b>v</b><sub>n</sub> ∈ Z<sup>n</sup> což je její dobrá báze, tedy její soukromý klíč. Tento výběr může provést například tak, že zafixuje <br>parametr z a vybere si souřadnice <b>v</b><sub>1</sub>, ..., <b>v</b><sub>n</sub> náhodně mezi -z a z." +
                                    "Jestli si vybrala opravdu dobrou bázi, si zkontroluje výpočtem Hadamardova poměru, který musí vyjít co nejblíže k 1. Vektory <b>v</b><sub>1</sub>, ..., <b>v</b><sub>n</sub> <br>generující mříž L, tvoří řady n/n matice V." +
                                    "Alice si dále zvolí n/n matici U s celočíselnými koeficienty a determinantem rovným ±1." +
                                    "Matici U dostaneme například jako produkt velkého počtu náhodně<br> vybraných elementárních matic." +
                                   "Dále vypočítá svůj veřejný klíč W = UV, tedy špatnou bázi <b>w</b><sub>1</sub>, ..., <b>w</b><sub>n</sub>, kterou pošle Bobovi." +
                                    "Bob chce poslat šifrovaně Alici nějakou informaci, například malý vektor <b>m</b>.</p>" +
                                    "<p>Dále si Bob musí vybrat malý náhodný odchýlený vektor <b>r</b>, což je efemérní klíč." +
                                    "Například si zvolí ω jako zafixovaný veřejný parametr a vybere si souřadnice <b>r</b> náhodně mezi –ω a ω.</p>" +
                                    "Nyní už může zašifrovat informaci <b>m</b> výpočtem <b>e</b> = <b>m</b>W + <b>r</b>, kde <b>e</b> je zašifrovaná informace, kterou Bob odešle Alici přes otevřený kanál." +
                                    "Protože <b>r</b> je malý, tak <b>e</b> není bodem mříže, ale nachází se<br> blízko u mřížového bodu <b>m</b>W." +
                                    "Alice použije na dešifrování Babaiův algoritmus spolu s dobrou bází <b>v</b><sub>1</sub>, ..., <b>v</b><sub>n</sub> k nalezení vektoru <b>v</b> v mříži L, který je blízko k e. Poté <b>m</b>W vynásobí W<sup>-1</sup> čímž obnoví <b>m</b>.</html>");
                            
                                    
        jText1.setFont(new Font("Times", 0, 10));
        text_border.add(jText1);
      
	contentPanel1.add(m_vectorBorder);
	contentPanel1.add(r_vectorBorder);
        contentPanel1.add(e_vectorBorder);
        contentPanel1.add(text_border);

        FunctionButtonHandler functionHandler = new FunctionButtonHandler();
        m_sampleButton.addActionListener(functionHandler);
        r_sampleButton.addActionListener(functionHandler);
        e_vectorButton.addActionListener(functionHandler);
      

        return contentPanel1;
    }

    public Matrix get_m_vector() {
        Matrix m_vector = new Matrix(1, GGHData.getInstance().getDimension());

        try {
                for (int i = 0; i < GGHData.getInstance().getDimension(); i++) {
                        m_vector.setElement(0, i, Double.valueOf(m_data[i].getText()));
                }
         }
         catch (NumberFormatException e) {         
            return null;
         }

        return m_vector;
    }

    public Matrix get_r_vector() {
        Matrix r_vector = new Matrix(1, GGHData.getInstance().getDimension());

        try {
                for (int i = 0; i < GGHData.getInstance().getDimension(); i++) {
                        r_vector.setElement(0, i, Double.valueOf(r_data[i].getText()));
                }
         }
         catch (NumberFormatException e) {         
            return null;
         }

        return r_vector;
    }

    public Matrix get_e_vector() {
        Matrix e_vector = new Matrix(1, GGHData.getInstance().getDimension());

        try {
                for (int i = 0; i < GGHData.getInstance().getDimension(); i++) {
                        e_vector.setElement(0, i, Double.valueOf(e_data[i].getText()));
                }
         }
         catch (NumberFormatException e) {           
            return null;
         }

        return e_vector;
    }

    private class FunctionButtonHandler implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
        Object src = evt.getSource();
            if (src == m_sampleButton) {
                 insert_m_vector();
            }
            else if (src == r_sampleButton) {
                 insert_r_vector();
            }
            else if (src == e_vectorButton) {
                 generate_e_vector();
            }
        }

        private void insert_m_vector() {
            Matrix m = GGHData.getInstance().generate_m_vector(GGHData.getInstance().getDimension());

            for (int i = 0; i < GGHData.getInstance().getDimension(); i++) {
                  m_data[i].setText(String.valueOf(m.getElement(0, i)));
            }
        }

        private void insert_r_vector() {
            Matrix r = GGHData.getInstance().generate_r_vector(GGHData.getInstance().getDimension());

            for (int i = 0; i < GGHData.getInstance().getDimension(); i++) {
                    r_data[i].setText(String.valueOf(r.getElement(0, i)));
            }
        }

        private void generate_e_vector() {
            Matrix m_vector = get_m_vector();
            Matrix r_vector = get_r_vector();

            if (m_vector == null || r_vector == null)
                return;


            //nastavit 'u' a 'v' vektor
            GGHData.getInstance().setM_vector(m_vector);
            GGHData.getInstance().setR_vector(r_vector);

            Matrix e = GGHData.getInstance().generate_e_vector(GGHData.getInstance().getDimension());

            for (int i = 0; i < GGHData.getInstance().getDimension(); i++) {
                    e_data[i].setText(String.valueOf(e.getElement(0, i)));
            }
        }
    }


    public JTextField[] getE_data() {
        return e_data;
    }

    public void setE_data(JTextField[] e_data) {
        this.e_data = e_data;
    }

    public JTextField[] getM_data() {
        return m_data;
    }

    public void setM_data(JTextField[] m_data) {
        this.m_data = m_data;
    }

    public JTextField[] getR_data() {
        return r_data;
    }

    public void setR_data(JTextField[] r_data) {
        this.r_data = r_data;
    }


}
