import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;

/**
 * Classe permettant la création de fenêtres pour la modification des arguments d'une méthode d'une classe.
 * @author V.BOULANGER
 */
public class ArgumentsPropertiesWindow extends JDialog {

    private UmlDiagram _umlDiagram;
    private Method _method;
    private JTable _argumentsTable;
    private JScrollPane _scrollArguments;
    private String[] _argumentsColumns = {"Name", "Type"};
    private DefaultTableModel _argumentModel;
    private ClassPropertiesWindow _classProp;

    public ArgumentsPropertiesWindow(ClassPropertiesWindow classProp, UmlDiagram diagram, Method m){
        _method = m;
        _umlDiagram = diagram;
        _classProp = classProp;

        //Paramétrage de la fenêtre
        this.setTitle("Edit arguments - " + m.getName());
        this.setModal(true);
        this.setSize(new Dimension(800, 375));
        Image img = null;
        try { img = ImageIO.read(AppThinker.class.getResource("img/logoAppThinker.png")); } catch (Exception ex) { }
        this.setIconImage(img);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.setLayout(new BorderLayout());

        //Espace général de la fenêtre
        JPanel generalPanel = new JPanel();
        generalPanel.setLayout(new BoxLayout(generalPanel, BoxLayout.Y_AXIS));
        generalPanel.setAlignmentX(LEFT_ALIGNMENT);

        JLabel attrLbl = new JLabel("Edit arguments");
        generalPanel.add(attrLbl);

        //Espace de modification des arguments
        JPanel argumentsPan = new JPanel();
        argumentsPan.setLayout(new BoxLayout(argumentsPan, BoxLayout.X_AXIS));

        _argumentModel = new DefaultTableModel(_argumentsColumns, 0);
        _argumentsTable = new JTable(_argumentModel);

        _scrollArguments = new JScrollPane(_argumentsTable);
        _scrollArguments.setPreferredSize(new Dimension(350, 100));
        argumentsPan.add(_scrollArguments);

        JPanel argumentsTableModifier = new JPanel();
        argumentsTableModifier.setLayout(new BoxLayout(argumentsTableModifier, BoxLayout.Y_AXIS));
        JButton addArgument = new JButton(" + ");
        addArgument.setToolTipText("Add a new argument.");
        addArgument.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                addArgument();
            }
        });
        argumentsTableModifier.add(addArgument);
        JButton removeArgument = new JButton(" -  ");
        removeArgument.setToolTipText("Remove the selected argument.");
        removeArgument.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                removeArgument();
            }
        });
        argumentsTableModifier.add(removeArgument);
        JButton upArgument = new JButton("▲");
        upArgument.setToolTipText("Go up the selected attribute.");
        upArgument.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int selected = _argumentsTable.getSelectedRow();
                if(_method.upArgument(selected)){
                    _umlDiagram.repaint();
                    listArguments();
                    _argumentsTable.setRowSelectionInterval(selected - 1, selected - 1);
                }
            }
        });
        argumentsTableModifier.add(upArgument);
        JButton downArgument = new JButton("▼");
        downArgument.setToolTipText("Go down the selected argument.");
        downArgument.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int selected = _argumentsTable.getSelectedRow();
                if(_method.downArgument(selected)){
                    _umlDiagram.repaint();
                    listArguments();
                    _argumentsTable.setRowSelectionInterval(selected + 1, selected + 1);
                }
            }
        });
        argumentsTableModifier.add(downArgument);

        argumentsPan.add(argumentsTableModifier);

        generalPanel.add(argumentsPan);

        this.add(generalPanel, BorderLayout.CENTER);

        //Import des arguments dans le tableau
        this.listArguments();

        this.addWindowListener(new WindowListener() {
            @Override
            public void windowOpened(WindowEvent e) {

            }

            @Override
            public void windowClosing(WindowEvent e) {
                save();
                dispose();
            }

            @Override
            public void windowClosed(WindowEvent e) {

            }

            @Override
            public void windowIconified(WindowEvent e) {

            }

            @Override
            public void windowDeiconified(WindowEvent e) {

            }

            @Override
            public void windowActivated(WindowEvent e) {

            }

            @Override
            public void windowDeactivated(WindowEvent e) {

            }
        });

        this.setVisible(true);
    }

    /**
     * Ajoute un argument à la méthode sélectionnée et rafraîchit la liste des arguments.
     */
    public void addArgument(){
        save();
        _method.addArgument(new Argument());
        _classProp.getEditingClass().computeMinSize();
        _umlDiagram.repaint();
        this.listArguments();
    }

    /**
     * Retire un argument à la méthode et rafraîchit la liste des arguments.
     */
    public void removeArgument(){
        int i = _argumentsTable.getSelectedRow();
        if(i != -1){
            save();
            _method.removeArgument(i);
            _classProp.getEditingClass().computeMinSize();
            _umlDiagram.repaint();
            this.listArguments();
        }
    }

    /**
     * Affiche la liste des arguments de la méthode dans le tableau
     */
    public void listArguments(){
        //Import des attributs dans la table
        _argumentModel.setDataVector((Object[][]) null, _argumentsColumns);
        for(Argument arg : _method.getArguments()){
            _argumentModel.addRow(new Object[]{arg.getName(), arg.getType()});
        }

        //On ajoute les contrôles pour chaque colonne
        JComboBox typeComboBox = new JComboBox();
        typeComboBox.setEditable(true);
        typeComboBox.addItem("boolean");
        typeComboBox.addItem("char");
        typeComboBox.addItem("byte");
        typeComboBox.addItem("short");
        typeComboBox.addItem("int");
        typeComboBox.addItem("long");
        typeComboBox.addItem("float");
        typeComboBox.addItem("double");
        typeComboBox.addItem("String");
        TableColumn typeColumn = _argumentsTable.getColumn(_argumentsColumns[1]);
        typeColumn.setCellEditor(new DefaultCellEditor(typeComboBox));
    }

    /**
     * Sauvegarde les modifications pour la méthode en cours et ferme la fenêtre.
     */
    public void save(){
        //Termine l'édition en sélectionnant une autre cellule
        _argumentsTable.editCellAt(0,0);
        //Enregistrement des attributs
        for(int i = 0; i <= _argumentModel.getRowCount()-1; i++){
            Vector vect = (Vector)_argumentModel.getDataVector().elementAt(i);
            System.out.println(vect);
            _method.getArguments().get(i).setType(vect.get(1).toString());
            _method.getArguments().get(i).setName(vect.get(0).toString());
        }
        //Rafraichissement de l'affichage
        _classProp.getEditingClass().computeMinSize();
        _umlDiagram.repaint();
    }
}
