package traduccion;

import javax.swing.JFrame;
import javax.swing.JDialog;
import java.awt.event.ActionListener;
import java.awt.event.WindowStateListener;
import java.awt.event.ActionEvent;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JList;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JComboBox;
import java.awt.Rectangle;
import java.awt.Font;
import javax.swing.SwingConstants;
import javax.swing.JButton;
import javax.swing.JTextField;
import myuml.MyObjects;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import de.fzi.XPath.*;
import de.fzi.XPath.Parser.*;
import java.io.StringReader;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
import java.util.StringTokenizer;
import java.awt.Frame;
import myuml.MyFrame;
import myuml.MyActor;
import myuml.MyLifeLine;
import myuml.MyMessage;
import java.awt.Component;
import javax.swing.ButtonGroup;
import javax.swing.JRadioButton;

/**
 * <p>Title: Hola a todos</p>
 *
 * <p>Description: este es el tutorial hola a todos</p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Company: Mi empresa</p>
 *
 * @author Mi nombre
 * @version 1.0
 */
public class VariablesMarco extends JDialog implements ActionListener  {
    MyObjects objeto;
    ArrayList al;

    public VariablesMarco(MyObjects obj,Frame f) {
        super(f,true);
        try {
            objeto = obj;
            al = objeto.getVariables();
            jbInit();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    //Ver si se ha seleccionado algún elemento de la lista de variables
    private class MyListenerSelection implements ListSelectionListener{

        public void valueChanged(ListSelectionEvent e){

            jButton1.setEnabled(true);

        }

    }


    public void actionPerformed(ActionEvent e) {
    }

    private void jbInit() throws Exception {
        setTitle(objeto.getName()+" variables");
        contentPane.setLayout(null);
        contentPane.setPreferredSize(new Dimension(1685, 494));
        setSize(new Dimension(450, 300));
        jScrollPane1.setBounds(new Rectangle(16, 37, 140, 180));
        jLabel1.setText("Defined variables");
        jLabel1.setFont(new java.awt.Font("Dialog", Font.BOLD, 16));
        jLabel1.setHorizontalAlignment(SwingConstants.CENTER);
        jLabel1.setHorizontalTextPosition(SwingConstants.CENTER);
        jLabel1.setBounds(new Rectangle(16, 14, 140, 18));
        jButton1.setBounds(new Rectangle(50, 232, 73, 23));
        jButton1.setText("Delete");
        jButton1.addActionListener(new VariablesMarco_jButton1_actionAdapter(this));
        jLabel2.setFont(new java.awt.Font("Dialog", Font.BOLD, 16));
        jLabel2.setText("Define new variable");
        jLabel2.setBounds(new Rectangle(192, 14, 225, 18));
        jLabel2.setHorizontalAlignment(SwingConstants.CENTER);
        jLabel2.setHorizontalTextPosition(SwingConstants.CENTER);
        jLabel3.setText("Name:");
        jLabel3.setBounds(new Rectangle(192, 55, 44, 18));
        jLabel3.setFont(new java.awt.Font("Dialog", Font.BOLD, 12));
        jLabel3.setHorizontalAlignment(SwingConstants.CENTER);
        jLabel3.setHorizontalTextPosition(SwingConstants.CENTER);
        jLabel4.setText("Type:");
        jLabel4.setBounds(new Rectangle(192, 100, 44, 14));
        jLabel4.setFont(new java.awt.Font("Dialog", Font.BOLD, 12));
        jLabel4.setHorizontalAlignment(SwingConstants.CENTER);
        jLabel4.setHorizontalTextPosition(SwingConstants.CENTER);
        jTextField1.setBounds(new Rectangle(244, 55, 136, 19));
        jComboBox2.setBounds(new Rectangle(244, 100, 136, 22));
        jComboBox2.addActionListener(new
                                     VariablesMarco_jComboBox2_actionAdapter(this));
        jButton2.setBounds(new Rectangle(272, 175, 73, 23));
        jButton2.setText("Add");
        jButton2.addActionListener(new VariablesMarco_jButton2_actionAdapter(this));
        contentPane.add(jScrollPane1);
        contentPane.add(jLabel1);
        contentPane.add(jButton1);
        contentPane.add(jLabel2);
        contentPane.add(jLabel3);
        contentPane.add(jLabel4);
        contentPane.add(jTextField1);
        contentPane.add(jComboBox2);
        contentPane.add(jButton2);

        //Para los valores de inicialización de las variables


        jLabel5.setText("Value:");
        jLabel5.setBounds(new Rectangle(192, 145, 44, 14));
        jLabel5.setFont(new java.awt.Font("Dialog", Font.BOLD, 12));
        jLabel5.setHorizontalAlignment(SwingConstants.CENTER);
        jLabel5.setHorizontalTextPosition(SwingConstants.CENTER);
        jLabel5.setVisible(false);

        //Si es un entero
        jTextField2.setBounds(new Rectangle(244, 145, 136, 19));
        jTextField2.setVisible(false);

        contentPane.add(jLabel5);
        contentPane.add(jTextField2);

        //Si es un booleano
        buttonGroup.add(radioButton1);
        buttonGroup.add(radioButton2);
        radioButton1.setBounds(new Rectangle(244, 145, 80, 19));
        radioButton2.setBounds(new Rectangle(320, 145, 80, 19));
        radioButton1.setVisible(false);
        radioButton2.setVisible(false);

        contentPane.add(radioButton1);
        contentPane.add(radioButton2);

        //Rellenar la lista con las variables del ArrayList del objeto
        //Recoger también el tipo
        String[] var =new String[al.size()];
        Object[] array =new Object[al.size()];

        array = al.toArray();

        for(int i = 0; i < var.length; i++){

            if(((String) ((Object[]) array[i])[2]).compareTo("")==0){
                var[i] = ((String) ((Object[]) array[i])[0]) + " - " +
                         ((String) ((Object[]) array[i])[1]);
            }
            else{
                var[i] = ((String) ((Object[]) array[i])[0]) + " = " +
                         ((String) ((Object[]) array[i])[2]) + " - " +
                         ((String) ((Object[]) array[i])[1]);
            }
        }

        jList1 = new JList(var);
        jList1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        jList1.addListSelectionListener(new MyListenerSelection());
        jButton1.setEnabled(false);
        jScrollPane1.getViewport().add(jList1);
    }

    JPanel contentPane = (JPanel) getContentPane();
    BorderLayout borderLayout1 = new BorderLayout();
    JScrollPane jScrollPane1 = new JScrollPane();


    JList jList1;
    JLabel jLabel1 = new JLabel();
    JButton jButton1 = new JButton();
    JLabel jLabel2 = new JLabel();
    JLabel jLabel3 = new JLabel();
    JLabel jLabel4 = new JLabel();
    JTextField jTextField1 = new JTextField();
    String[] types = {"Clock","Integer","String","Boolean","Exception"};
    JComboBox jComboBox2 = new JComboBox(types);
    JButton jButton2 = new JButton();

    JLabel jLabel5 = new JLabel();
    JTextField jTextField2 = new JTextField();
    ButtonGroup buttonGroup = new ButtonGroup();
    JRadioButton radioButton1 = new JRadioButton("True");
    JRadioButton radioButton2 = new JRadioButton("False");


    public void jButton2_actionPerformed(ActionEvent e) {

        //Ver que no exista ya una variable con el mismo nombre en ninguno de
        //los actores o lifelines existentes, incluido el objeto actual
        JPanel jPanelDraw = (JPanel) objeto.getParent();
        boolean existe = false;
        XPathParser parseo = new XPathParser(new StringReader(jTextField1.getText()));
        Component[] lista = jPanelDraw.getComponents();

        for (int i = 0; i < lista.length; i++) {

            //Si se trata de un Actor o de un LifeLine
            if ((lista[i] instanceof MyActor) || (lista[i] instanceof MyLifeLine)) {

                ArrayList lista_var = ((MyObjects)lista[i]).getVariables();

                for(int j = 0; j < lista_var.size(); j++){
                    if (((String) ((Object[]) lista_var.get(j))[0]).compareTo(jTextField1.getText()) == 0) {

                        existe = true;
                        break;

                    }
                }

            }

            if(existe) break;

        }

        if(existe){

            //Mostrar el aviso de que la variable ya existe
            JOptionPane optionPane= new JOptionPane();
            Object[] options = {"Ok"};
            optionPane.showOptionDialog(optionPane,
                                        "Variable name already exists",
                                        "Message", optionPane.YES_NO_OPTION,
                                        optionPane.ERROR_MESSAGE, null,
                                        options, null);

        }

        else{

            //Ver que sea una variable XPath valida
            try {
                String res_parseo = parseo.QName();

                if((res_parseo.length()==jTextField1.getText().length()) && (res_parseo.compareTo("true")!=0) && (res_parseo.compareTo("false")!=0)){

                    //Si es una variable válida que no existe todavía

                    boolean valido=true;
                    String valor = "";

                    //Si es una variable de tipo integer se debe comprobar si se ha
                    //definido un valor inicial que sea válido
                    if(jComboBox2.getSelectedItem().toString().compareTo("Integer")==0){

                        if(jTextField2.getText().compareTo("")!=0){

                            try{

                                Integer.parseInt(jTextField2.getText());

                                valor = jTextField2.getText();

                            }
                            catch(NumberFormatException nfe){valido=false;}
                        }

                    }

                    //Si es una variable de tipo string se debe recoger el valor
                    else if(jComboBox2.getSelectedItem().toString().compareTo("String")==0){

                        valor = jTextField2.getText();

                    }
                    //Si es una variable booleana
                    else if(jComboBox2.getSelectedItem().toString().compareTo("Boolean")==0){

                            if (radioButton1.isSelected()) {

                                valor = "true";

                            }

                            else {

                                valor = "false";

                            }
                    }

                    //Si es válido el valor de la variable
                    if(valido){

                        Object[] new_var = new Object[3];

                        new_var[0] = jTextField1.getText();
                        new_var[1] = jComboBox2.getSelectedItem().toString();
                        new_var[2] = valor;

                        al.add(new_var);

                        //Rellenar la lista incluyendo la nueva variable
                        String[] var = new String[al.size()];
                        Object[] array = new Object[al.size()];

                        array = al.toArray();

                        for (int i = 0; i < var.length; i++) {

                            if(((String) ((Object[]) array[i])[2]).compareTo("")!=0){

                                var[i] = ((String) ((Object[]) array[i])[0]) + " = " +
                                         ((String) ((Object[]) array[i])[2]) + " - " +
                                         ((String) ((Object[]) array[i])[1]);

                            }
                            else{

                                var[i] = ((String) ((Object[]) array[i])[0]) + " - " +
                                         ((String) ((Object[]) array[i])[1]);

                            }

                        }

                        jList1 = new JList(var);
                        jList1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                        jList1.addListSelectionListener(new MyListenerSelection());
                        jButton1.setEnabled(false);
                        jScrollPane1.getViewport().add(jList1);

                        //Volver a dejar vacío el campo de texto
                        jTextField1.setText("");

                        //Fijar el nuevo arrayList del objeto
                        objeto.setVariables(al);

                        //Dejar también los campos de valor a sus valores por defecto
                        jTextField2.setText("");
                        radioButton2.setSelected(true);

                    }
                    else{

                        //Mostrar el aviso de que no se trata de un valor de variable válido
                        JOptionPane optionPane = new JOptionPane();
                        Object[] options = {"Ok"};
                        optionPane.showOptionDialog(optionPane,
                                "Invalid variable value",
                                "Message", optionPane.YES_NO_OPTION,
                                optionPane.ERROR_MESSAGE, null,
                                options, null);


                    }
                }

                else{

                    //Mostrar el aviso de que no se trata de una variable válida
                    JOptionPane optionPane = new JOptionPane();
                    Object[] options = {"Ok"};
                    optionPane.showOptionDialog(optionPane,
                                                "Invalid variable name",
                                                "Message", optionPane.YES_NO_OPTION,
                                                optionPane.ERROR_MESSAGE, null,
                                                options, null);

                }

            } catch (Throwable t) {

                //Mostrar el aviso de que no se trata de una variable válida
                JOptionPane optionPane= new JOptionPane();
                Object[] options = {"Ok"};
                optionPane.showOptionDialog(optionPane,
                                            "Invalid variable name",
                                            "Message", optionPane.YES_NO_OPTION,
                                            optionPane.ERROR_MESSAGE, null,
                                            options, null);

            }

        }
    }

    public void jButton1_actionPerformed(ActionEvent e) {

        JOptionPane optionPane= new JOptionPane();

        Object[] options = {"Yes","No","Cancel"};

        int ret=optionPane.showOptionDialog(optionPane,"Do you want to delete the selected variable?","Delete",optionPane.YES_NO_CANCEL_OPTION,optionPane.QUESTION_MESSAGE, null, options, null);
        if (ret==JOptionPane.YES_OPTION){

            StringTokenizer st = new StringTokenizer(jList1.getSelectedValue().
                    toString());

            if (st.hasMoreTokens()) {

                String var_new = st.nextToken();

                //Comprobar que la variable no se esté utilizando en ninguno de los frames definidos
                //o en un timeout de un mensaje
                JPanel jPanelDraw = (JPanel) objeto.getParent();
                boolean usada = false;
                Component[] lista = jPanelDraw.getComponents();

                for (int i = 0; i < lista.length; i++) {

                    //Si se trata de un Frame
                    if (lista[i] instanceof MyFrame) {

                        ArrayList lista_var_guarda = ((MyFrame) lista[i]).getVariablesGuarda();
                        ArrayList lista_var_repeat = ((MyFrame) lista[i]).getVariablesRepeat();

                        for (int j = 0; j < lista_var_guarda.size(); j++) {
                            if (((String)(lista_var_guarda.get(j))).compareTo(var_new) == 0) {

                                usada = true;
                                break;

                            }
                        }

                        for (int j = 0; j < lista_var_repeat.size(); j++) {
                            if (((String)(lista_var_repeat.get(j))).compareTo(var_new) == 0) {

                                usada = true;
                                break;

                            }
                        }

                        //Si tiene excepción asociada
                        String exception_manage=((MyFrame) lista[i]).getException();

                        //Si es un timeout nos quedamos solo con lo anterior al simbolo <
                        if(exception_manage.contains("<")) exception_manage = exception_manage.substring(0,exception_manage.indexOf("<"));

                        if(exception_manage.compareTo(var_new) == 0) usada = true;

                    }

                    //Si se trata de un mensaje
                    if (lista[i] instanceof MyMessage) {

                        String reloj_timeout = ((MyMessage) lista[i]).getTimeout_clock();
                        String exception_caused = ((MyMessage) lista[i]).getException_variable();
                        String send_variable = ((MyMessage) lista[i]).getSend_variable();
                        String receive_variable = ((MyMessage) lista[i]).getReceive_variable();

                        if (reloj_timeout.compareTo(var_new) == 0 || exception_caused.compareTo(var_new)==0
                                || send_variable.compareTo(var_new)==0 || receive_variable.compareTo(var_new)==0)
                            usada = true;
                    }

                    if (usada)
                        break;

                }

                if(usada){

                    //Mostrar el aviso de que no se puede borrar la variable
                    JOptionPane optionPane2 = new JOptionPane();
                    Object[] options2 = {"Ok"};
                    optionPane2.showOptionDialog(optionPane2,
                                                "Variable cannot be deleted, it is being used",
                                                "Message", optionPane2.YES_NO_OPTION,
                                                optionPane2.ERROR_MESSAGE, null,
                                                options2, null);


                }

                else{

                    for (int i = 0; i < al.size(); i++) {

                        //Eliminar de la lista si coincide el nombre con el de la variable
                        if (((String) ((Object[]) al.get(i))[0]).compareTo(var_new) ==
                            0) {

                            al.remove(i);
                            break;

                        }

                    }

                    //Rellenar la lista borrando la variable
                    String[] var = new String[al.size()];
                    Object[] array = new Object[al.size()];

                    array = al.toArray();

                    for (int i = 0; i < var.length; i++) {

                        if(((String) ((Object[]) array[i])[2]).compareTo("")!=0){

                            var[i] = ((String) ((Object[]) array[i])[0]) + " = " +
                                     ((String) ((Object[]) array[i])[2]) + " - " +
                                     ((String) ((Object[]) array[i])[1]);

                        }
                        else{

                            var[i] = ((String) ((Object[]) array[i])[0]) + " - " +
                                     ((String) ((Object[]) array[i])[1]);

                        }

                    }

                    jList1 = new JList(var);
                    jList1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                    jList1.addListSelectionListener(new MyListenerSelection());
                    jButton1.setEnabled(false);
                    jScrollPane1.getViewport().add(jList1);

                    //Fijar el nuevo arrayList del objeto
                    objeto.setVariables(al);

                    //También se debe borrar cualquier actualización que se haya
                    //hecho de la variable en alguno de los mensajes del diagrama
                    for (int i = 0; i < lista.length; i++) {

                        //Si se trata de un mensaje
                        if (lista[i] instanceof MyMessage) {

                            ArrayList upd = ((MyMessage) lista[i]).getUpdates();

                            for (int j = 0; j < upd.size(); j++) {
                                if (((String) ((Object[]) upd.get(j))[0]).compareTo(var_new) == 0) {

                                    //Eliminar la actualización correspondiente
                                    upd.remove(j);
                                    ((MyMessage) lista[i]).setUpdates(upd);
                                    break;

                                }
                            }

                        }

                    }

                }
            }

        }
    }

    public void jComboBox2_actionPerformed(ActionEvent e) {

        //Hacer visible el componente que corresponda según el elemento seleccionado

        //Se hace invisible cuando es un clock
        if(jComboBox2.getSelectedIndex() == 0){

            radioButton1.setVisible(false);
            radioButton2.setVisible(false);
            jTextField2.setVisible(false);
            jLabel5.setVisible(false);


        }

        //Se hace visible el campo de texto para integer
        else if(jComboBox2.getSelectedIndex() == 1){

            radioButton1.setVisible(false);
            radioButton2.setVisible(false);
            jTextField2.setVisible(true);
            jLabel5.setVisible(true);

            //Dejar en blanco el campo de texto
            jTextField2.setText("");
        }

        //Se hace visible el campo de texto para string
        else if(jComboBox2.getSelectedIndex() == 2){

            radioButton1.setVisible(false);
            radioButton2.setVisible(false);
            jTextField2.setVisible(true);
            jLabel5.setVisible(true);

            //Dejar en blanco el campo de texto
            jTextField2.setText("");
        }

        //Se hacen visible los radiobutton para booleanos
        else if(jComboBox2.getSelectedIndex() == 3){

            radioButton1.setVisible(true);
            radioButton2.setVisible(true);
            jTextField2.setVisible(false);
            jLabel5.setVisible(true);

            //Dejar el valor false seleccionado por defecto
            radioButton2.setSelected(true);

        }

        else{

            radioButton1.setVisible(false);
            radioButton2.setVisible(false);
            jTextField2.setVisible(false);
            jLabel5.setVisible(false);

        }

    }
}


class VariablesMarco_jComboBox2_actionAdapter implements ActionListener {
    private VariablesMarco adaptee;
    VariablesMarco_jComboBox2_actionAdapter(VariablesMarco adaptee) {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e) {
        adaptee.jComboBox2_actionPerformed(e);
    }
}


class VariablesMarco_jButton2_actionAdapter implements ActionListener {
    private VariablesMarco adaptee;
    VariablesMarco_jButton2_actionAdapter(VariablesMarco adaptee) {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e) {
        adaptee.jButton2_actionPerformed(e);
    }
}


class VariablesMarco_jButton1_actionAdapter implements ActionListener {
    private VariablesMarco adaptee;
    VariablesMarco_jButton1_actionAdapter(VariablesMarco adaptee) {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e) {
        adaptee.jButton1_actionPerformed(e);
    }
}
