package com.uvigo.mhp.xml;

import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.xml.bind.*;
import com.uvigo.mhp.textPanel.*;
import com.uvigo.mhp.xml.textPanel.*;

public class TextPanelContentEditorPanel extends JPanel implements ListSelectionListener
{
    private DefaultListModel listModel;
    private DefaultListSelectionModel selectionModel;
    private DefaultTableModel tableModel;
    private boolean moving;
    
    private JAXBContext jc;
    private ObjectFactory objFactory;
    private DocumentList documents;
    private java.util.List resources;
    private java.util.List currentAnchorList;
    private Vector loaded; // indica si se han cargado las anclas de cada documento
    private Document former;
    
    public TextPanelContentEditorPanel()
    {
        initComponents();
        try
        {
            jc=JAXBContext.newInstance("com.uvigo.mhp.xml.textPanel");
            objFactory = new ObjectFactory();
            documents = objFactory.createDocumentList();
            resources = documents.getResource();
            
            loaded=new Vector();
            textPanel1.setDocument(new HTMLDocument());
            
            listModel=new DefaultListModel();
            jList1.setModel(listModel);
            tableModel=(DefaultTableModel) jTable1.getModel();
            selectionModel=(DefaultListSelectionModel) jTable1.getSelectionModel();
            jList1.addListSelectionListener(this);
            moving=false;
            former=null;
        }
        catch (JAXBException ex)
        {
            System.out.println(ex.getMessage());
        }
    }
    
    private void initComponents()//GEN-BEGIN:initComponents
    {
        jPanel13 = new javax.swing.JPanel();
        jButton12 = new javax.swing.JButton();
        jButton11 = new javax.swing.JButton();
        jButton10 = new javax.swing.JButton();
        jSplitPane1 = new javax.swing.JSplitPane();
        jPanel1 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jPanel5 = new javax.swing.JPanel();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jPanel3 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();
        jSplitPane2 = new javax.swing.JSplitPane();
        jPanel10 = new javax.swing.JPanel();
        jPanel11 = new javax.swing.JPanel();
        jButton5 = new javax.swing.JButton();
        jButton6 = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jScrollPane3 = new javax.swing.JScrollPane();
        textPanel1 = new com.uvigo.mhp.textPanel.TextPanel();

        setLayout(new java.awt.BorderLayout());

        jPanel13.setLayout(new java.awt.GridLayout(1, 0));

        jButton12.setText("Nuevo");
        jButton12.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jButton12ActionPerformed(evt);
            }
        });

        jPanel13.add(jButton12);

        jButton11.setText("Cargar");
        jButton11.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jButton11ActionPerformed(evt);
            }
        });

        jPanel13.add(jButton11);

        jButton10.setText("Guardar como...");
        jButton10.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jButton10ActionPerformed(evt);
            }
        });

        jPanel13.add(jButton10);

        add(jPanel13, java.awt.BorderLayout.SOUTH);

        jSplitPane1.setDividerLocation(150);
        jSplitPane1.setDividerSize(5);
        jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jPanel1.setLayout(new java.awt.BorderLayout());

        jPanel1.setBorder(new javax.swing.border.TitledBorder("Localizadores "));
        jPanel2.setLayout(new java.awt.BorderLayout());

        jScrollPane1.setViewportView(jList1);

        jPanel2.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jPanel5.setLayout(new java.awt.GridLayout(0, 1));

        jButton2.setText("<");
        jButton2.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jButton2ActionPerformed(evt);
            }
        });

        jPanel5.add(jButton2);

        jButton3.setText(">");
        jButton3.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jButton3ActionPerformed(evt);
            }
        });

        jPanel5.add(jButton3);

        jPanel2.add(jPanel5, java.awt.BorderLayout.WEST);

        jPanel1.add(jPanel2, java.awt.BorderLayout.CENTER);

        jPanel3.setLayout(new java.awt.GridLayout(1, 0));

        jButton1.setText("+");
        jButton1.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jButton1ActionPerformed(evt);
            }
        });

        jPanel3.add(jButton1);

        jButton4.setText("-");
        jButton4.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jButton4ActionPerformed(evt);
            }
        });

        jPanel3.add(jButton4);

        jPanel1.add(jPanel3, java.awt.BorderLayout.SOUTH);

        jSplitPane1.setLeftComponent(jPanel1);

        jSplitPane2.setDividerLocation(200);
        jSplitPane2.setDividerSize(5);
        jPanel10.setLayout(new java.awt.BorderLayout());

        jPanel11.setLayout(new java.awt.GridLayout(1, 0));

        jButton5.setText("Todas");
        jButton5.setToolTipText("Recupera todas las anclas del documento");
        jButton5.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jButton5ActionPerformed(evt);
            }
        });

        jPanel11.add(jButton5);

        jButton6.setText("Eliminar");
        jButton6.setToolTipText("Elimina las anclas seleccionadas, de modo que no delimitan contextos");
        jButton6.addActionListener(new java.awt.event.ActionListener()
        {
            public void actionPerformed(java.awt.event.ActionEvent evt)
            {
                jButton6ActionPerformed(evt);
            }
        });

        jPanel11.add(jButton6);

        jPanel10.add(jPanel11, java.awt.BorderLayout.SOUTH);

        jScrollPane2.setAutoscrolls(true);
        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][]
            {

            },
            new String []
            {
                "Ancla", "Contexto", "Texto"
            }
        )
        {
            Class[] types = new Class []
            {
                java.lang.String.class, java.lang.String.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean []
            {
                false, true, true
            };

            public Class getColumnClass(int columnIndex)
            {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex)
            {
                return canEdit [columnIndex];
            }
        });
        jTable1.setCellSelectionEnabled(true);
        jTable1.setEditingColumn(1);
        jTable1.setEditingRow(1);
        jTable1.setOpaque(false);
        jTable1.addMouseListener(new java.awt.event.MouseAdapter()
        {
            public void mouseClicked(java.awt.event.MouseEvent evt)
            {
                jTable1MouseClicked(evt);
            }
        });

        jScrollPane2.setViewportView(jTable1);

        jPanel10.add(jScrollPane2, java.awt.BorderLayout.CENTER);

        jSplitPane2.setLeftComponent(jPanel10);

        textPanel1.addPropertyChangeListener(new java.beans.PropertyChangeListener()
        {
            public void propertyChange(java.beans.PropertyChangeEvent evt)
            {
                textPanel1PropertyChange(evt);
            }
        });

        jScrollPane3.setViewportView(textPanel1);

        jSplitPane2.setRightComponent(jScrollPane3);

        jSplitPane1.setRightComponent(jSplitPane2);

        add(jSplitPane1, java.awt.BorderLayout.CENTER);

    }//GEN-END:initComponents
    
    private void textPanel1PropertyChange(java.beans.PropertyChangeEvent evt)//GEN-FIRST:event_textPanel1PropertyChange
    {//GEN-HEADEREND:event_textPanel1PropertyChange
        // se viene por aqui cada vez que el textPanel termina de cargar un documento;
        // es el momento de cargar la tabla de anclas (inicializando currentAnchorList
        // si asi lo indica el vector loaded)
        
        System.out.println("HOLA");
        if (!(evt.getPropertyName().equalsIgnoreCase("page")))
            return;
        
        Document d = textPanel1.getDocument();
        
        if (d==former) return;
        former=d;
        
        int selected=jList1.getSelectedIndex();
        ResourceType rt=(ResourceType) resources.get(selected);
        currentAnchorList=rt.getAnchor();
        
        // Si en el vector loaded la entrada correspondiente a la selecci�n est�
        // a false, hay que inicializar la tabla de anclas
        if (loaded.get(selected).equals(Boolean.FALSE))
        {
            loaded.set(selected, new Boolean(true));
            if (d instanceof HTMLDocument)
            {
                HTMLDocument doc = (HTMLDocument) d;
                HTMLDocument.Iterator iter = doc.getIterator(HTML.Tag.A);
                
                try
                {
                    for (; iter.isValid(); iter.next())
                    {
                        AttributeSet a = iter.getAttributes();
                        String nm = (String) a.getAttribute(HTML.Attribute.NAME);
                        if ((nm==null) || (nm.equals(""))) continue;
                        
                        AnchorType at=objFactory.createAnchorType();
                        at.setAnchor(nm);
                        currentAnchorList.add(at);
                    }
                }
                catch (Exception ex)
                {
                    ex.printStackTrace();
                }
            }
        }
        
        for (int i=0;i<currentAnchorList.size();i++)
        {
            AnchorType at=(AnchorType) currentAnchorList.get(i);
            Object temp[]=new Object[3];
            temp[0]=at.getAnchor();
            temp[1]=at.getContextName();
            temp[2]=at.getComment();
            tableModel.addRow(temp);
        }
    }//GEN-LAST:event_textPanel1PropertyChange
    
    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jButton4ActionPerformed
    {//GEN-HEADEREND:event_jButton4ActionPerformed
        // eliminar una entrada en la lista de localizadores
        
        int i=jList1.getSelectedIndex();
        if (i==-1) return;
        listModel.remove(i);
        resources.remove(i);
        loaded.remove(i);
        
        if (listModel.size()==0)
        {
            int j=tableModel.getRowCount();
            for (int k=0;k<j;k++)
                tableModel.removeRow(0);
            textPanel1.setDocument(new HTMLDocument());
            return;
        }
        
        // la actualizaci�n de la tabla se lleva a cabo en la atenci�n
        // del cambio de selecci�n en la lista.
        if (i==listModel.size())
            jList1.setSelectedIndex(i-1);
        else
            jList1.setSelectedIndex(i);
    }//GEN-LAST:event_jButton4ActionPerformed
    
    private void jButton12ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jButton12ActionPerformed
    {//GEN-HEADEREND:event_jButton12ActionPerformed
        // hay que reinicializar todos los componentes
        
        listModel.clear();
        int j=tableModel.getRowCount();
        for (int i=0;i<j;i++)
            tableModel.removeRow(0);
        textPanel1.setDocument(new HTMLDocument());
        
        try
        {
            documents = objFactory.createDocumentList();
            resources = documents.getResource();
            loaded.clear();
        }
        catch (Exception ex)
        {
            System.out.println(ex.getMessage());
        }
    }//GEN-LAST:event_jButton12ActionPerformed
    
    private void jButton11ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jButton11ActionPerformed
    {//GEN-HEADEREND:event_jButton11ActionPerformed
        // hay que cargar el contenido de un fichero XML
        
        jButton12ActionPerformed(null); // lo primero es reinicializar el entorno
        
        javax.swing.JFileChooser chooser = new javax.swing.JFileChooser();
        int option = chooser.showOpenDialog(this);
        if (option == javax.swing.JFileChooser.APPROVE_OPTION)
        {
            try
            {
                File file = chooser.getSelectedFile();
                if (file == null) return;
                
                Unmarshaller u=jc.createUnmarshaller();
                u.setValidating(true);
                documents=(DocumentList) u.unmarshal(new FileInputStream(file));
                resources=documents.getResource();
                loaded=new Vector(resources.size());
                
                for (int i=0;i<resources.size();i++)
                {
                    ResourceType rt=(ResourceType) resources.get(i);
                    listModel.addElement(rt.getLocator());
                    loaded.add(new Boolean(true));
                }
                
                if (listModel.size()>0)
                    jList1.setSelectedIndex(0);
            }
            catch (Exception ex)
            {
                System.out.println(ex);
            }
        }
    }//GEN-LAST:event_jButton11ActionPerformed
    
    private void jButton10ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jButton10ActionPerformed
    {//GEN-HEADEREND:event_jButton10ActionPerformed
        // hay que grabar un fichero XML con el contenido creado
        
        javax.swing.JFileChooser chooser = new javax.swing.JFileChooser();
        int option = chooser.showSaveDialog(this);
        if (option == javax.swing.JFileChooser.APPROVE_OPTION)
        {
            try
            {
                File file = chooser.getSelectedFile();
                if (file == null) return;
                
                if (currentAnchorList!=null)
                    for (int i=0;i<currentAnchorList.size();i++)
                    {
                        AnchorType at=(AnchorType) currentAnchorList.get(i);
                        at.setAnchor((String) tableModel.getValueAt(i,0));
                        at.setContextName((String) tableModel.getValueAt(i,1));
                        at.setComment((String) tableModel.getValueAt(i,2));
                    }
                
                Marshaller m = jc.createMarshaller();
                m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
                m.marshal(documents, new FileOutputStream(file));
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
                System.out.println(ex);
            }
        }
    }//GEN-LAST:event_jButton10ActionPerformed
    
    private void jTable1MouseClicked(java.awt.event.MouseEvent evt)//GEN-FIRST:event_jTable1MouseClicked
    {//GEN-HEADEREND:event_jTable1MouseClicked
        // Cuando se selecciona un ancla en la tabla se reposiciona el documento mostrado
        
        Point p=new Point(evt.getX(),evt.getY());
        int col=jTable1.columnAtPoint(p);
        int fil=jTable1.rowAtPoint(p);
        if ((col==-1) || (fil==-1)) return;
        
        AnchorType at=(AnchorType) currentAnchorList.get(fil);
        textPanel1.scrollToReference(at.getAnchor());
    }//GEN-LAST:event_jTable1MouseClicked
    
    private void jButton5ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jButton5ActionPerformed
    {//GEN-HEADEREND:event_jButton5ActionPerformed
        // hay que recargar todas las anclas del documento
        
        if (jList1.getSelectedIndex()==-1)
            return;
        
        currentAnchorList.clear();
        
        int j=tableModel.getRowCount();
        for (int k=0;k<j;k++)
            tableModel.removeRow(0);
        
        Document d = textPanel1.getDocument();
        
        if (d instanceof HTMLDocument)
        {
            HTMLDocument doc = (HTMLDocument) d;
            HTMLDocument.Iterator iter = doc.getIterator(HTML.Tag.A);
            
            try
            {
                for (; iter.isValid(); iter.next())
                {
                    AttributeSet a = iter.getAttributes();
                    String nm = (String) a.getAttribute(HTML.Attribute.NAME);
                    if ((nm==null) || (nm.equals(""))) continue;
                    
                    Object temp[]=new Object[3];
                    temp[0]=nm;
                    temp[1]=new String("");
                    temp[2]=new String("");
                    tableModel.addRow(temp);
                    
                    AnchorType at=objFactory.createAnchorType();
                    at.setAnchor(nm);
                    currentAnchorList.add(at);
                }
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }
    }//GEN-LAST:event_jButton5ActionPerformed
    
    private void jButton6ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jButton6ActionPerformed
    {//GEN-HEADEREND:event_jButton6ActionPerformed
        // hay que borrar las anclas seleccionadas en la tabla
        
        int i[]=jTable1.getSelectedRows();
        if (i.length==0) return;
        
        for (int j=0;j<i.length;j++)
        {
            tableModel.removeRow(i[j]-j);
            currentAnchorList.remove(i[j]-j);
        }
        
        if (jTable1.getRowCount()==0) return;
        if (i[0]==jTable1.getRowCount())
        {
            jTable1.setColumnSelectionInterval(0, 0);
            jTable1.setRowSelectionInterval(i[0]-1, i[0]-1);
        }
        else
        {
            jTable1.setColumnSelectionInterval(0, 0);
            jTable1.setRowSelectionInterval(i[0], i[0]);
        }
    }//GEN-LAST:event_jButton6ActionPerformed
    
    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        // desplazar hacia abajo el localizador (afecta cuando los contextos
        // se secuencian por medio de los m�todos nextContext o previousContext)
        
        int i=jList1.getSelectedIndex();
        if (i==-1) return;
        if (i==listModel.size()-1) return;
        
        moving=true;
        Object aux=listModel.get(i);
        Object aux2=listModel.get(i+1);
        listModel.set(i,aux2);
        listModel.set(i+1,aux);
        
        aux=resources.get(i);
        aux2=resources.get(i+1);
        resources.set(i,aux2);
        resources.set(i+1,aux);
        
        aux=loaded.get(i);
        aux2=loaded.get(i+1);
        loaded.set(i,aux2);
        loaded.set(i+1,aux);
        
        jList1.setSelectedIndex(i+1);
    }//GEN-LAST:event_jButton3ActionPerformed
    
    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        // desplazar hacia arriba el localizador
        
        int i=jList1.getSelectedIndex();
        if (i==-1) return;
        if (i==0) return;
        
        moving=true;
        Object aux=listModel.get(i);
        Object aux2=listModel.get(i-1);
        listModel.set(i,aux2);
        listModel.set(i-1,aux);
        
        aux=resources.get(i);
        aux2=resources.get(i-1);
        resources.set(i,aux2);
        resources.set(i-1,aux);
        
        aux=loaded.get(i);
        aux2=loaded.get(i-1);
        loaded.set(i,aux2);
        loaded.set(i-1,aux);
        
        jList1.setSelectedIndex(i-1);
    }//GEN-LAST:event_jButton2ActionPerformed
    
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        // a�adir un nuevo localizador
        
        javax.swing.JFileChooser chooser = new javax.swing.JFileChooser();
        int option = chooser.showOpenDialog(this);
        if (option == javax.swing.JFileChooser.APPROVE_OPTION)
        {
            try
            {
                File file = chooser.getSelectedFile();
                if (file == null) return;
                
                listModel.addElement(file.toURL());
                
                ResourceType rt=objFactory.createResourceType();
                rt.setLocator(file.toURL().toString());
                resources.add(rt);
                loaded.add(new Boolean(false));
                jList1.setSelectedIndex(listModel.size()-1);
            }
            catch (Exception ex)
            {
                System.out.println(ex);
            }
        }
    }//GEN-LAST:event_jButton1ActionPerformed
    
    public void valueChanged(ListSelectionEvent evt)
    {
        // al cambiar el localizador seleccionado, hay que cambiar el documento que
        // se muestra y actualizar la tabla de anclas
 
        if(evt.getValueIsAdjusting())
            return;
        
        int selected=jList1.getSelectedIndex();
        if (selected==-1)
            return;
        
        if (moving)
        {
            moving=false;
            return;
        }
        
        int j=tableModel.getRowCount();
        for (int i=0;i<j;i++)
            tableModel.removeRow(0);
        
        ResourceType rt=(ResourceType) resources.get(selected);
        
        try
        {
            textPanel1.setPage(new URL(rt.getLocator()));
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
    
    public Dimension getPreferredSize()
    {
        return new Dimension(600,400);
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JPanel jPanel13;
    private javax.swing.JSplitPane jSplitPane2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel10;
    private javax.swing.JButton jButton1;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JButton jButton12;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JButton jButton11;
    private javax.swing.JButton jButton3;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel11;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JButton jButton10;
    private javax.swing.JButton jButton6;
    private javax.swing.JList jList1;
    private javax.swing.JButton jButton5;
    private com.uvigo.mhp.textPanel.TextPanel textPanel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JButton jButton4;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTable jTable1;
    // End of variables declaration//GEN-END:variables
}