/*
 * TopologyPanel.java
 *
 * Created on December 17, 2004, 2:01 PM
 */

package DDMT.core;

import javax.swing.*;
import java.io.*;
import java.awt.*;
import DDMT.Nodes.Node;
import DDMT.Nodes.Neighbor;
import java.util.regex.*;
import java.text.*;
import java.util.Vector;

/**
 *
 * @author  jk3
 */
public class TopologyPanel extends DDMT.core.DefaultPanel {
    
    //This is the pattern for one line of a BRITE format file representing a node
    private Pattern nodePattern = Pattern.compile("\\s*\\d+\\s+\\S+\\s+\\S+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\S*\\s*");
    private Matcher nodeMatcher;
    
    //This is the pattern for one line of a BRITE format file representing an edge
    private Pattern edgePattern = 
        Pattern.compile("\\s*\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\p{Punct}\\d+\\s+\\d+\\p{Punct}\\d+\\s+\\d+\\p{Punct}\\d+\\s+\\d+\\s+\\d+\\s+\\S*\\s?\\S*\\s*");
    private Matcher edgeMatcher;
    
    //Define the pattern for the line containing the number of nodes
    private Pattern numNodesP = Pattern.compile("(\\s\\d+\\s)");
    private Matcher numNodesM;
    
    //Pattern for outputting decimal numbers
    private String floatPattern = new String("#####.########");
    private DecimalFormat floatFormat = new DecimalFormat(floatPattern);
    
    //The file to read the topology from
    private File file = null;
    
    //The file readers to read the file from
    private FileReader reader = null;
    private BufferedReader bReader = null;
    
    //The file chooser for opening the topology file
    final JFileChooser fc = new JFileChooser();
    
    /** Creates new form TopologyPanel */
    public TopologyPanel(DDMT.core.MainPanel.ControlClass cClass ) {
        initComponents();
        
        controlClass = cClass;
        
        //Set the main window's tab name for this panel
        this.setName("Topology Import");
    }
    
    /**
     *Method that will tell the panel to save all it's data to files so that other
     *panels can then use it.  The file that this panel saves is nodes.txt, which
     *holds a list of all the nodes in the system.
     */
    public void save()
    {
        //Make sure that a project is selected
        if( controlClass.getProjectName() == null )
        {
            controlClass.showError("Topology Import: Error: No project selected!");
            return;
        }
            
        //Clear out all files that will be made irrelevant by this load
        File old0 = new File("Files\\Projects\\"+controlClass.getProjectName()+"\\NodeClassMatching.txt");
        File old1 = new File("Files\\Projects\\"+controlClass.getProjectName()+"\\heteroDist.txt");
        File old2 = new File("Files\\Projects\\"+controlClass.getProjectName()+"\\probVector.txt");
        File old3 = new File("Files\\Projects\\"+controlClass.getProjectName()+"\\distribution.txt");
        File old4 = new File("Files\\Projects\\"+controlClass.getProjectName()+"\\locations.txt");
        File old5 = new File("Files\\Projects\\"+controlClass.getProjectName()+"\\columns.txt");
        File old6 = new File("Files\\Projects\\"+controlClass.getProjectName()+"\\partitionTypes.txt");
        if( old0.exists() )
            old0.delete();
        if( old1.exists() )
            old1.delete();
        if( old2.exists() )
            old2.delete();
        if( old3.exists() )
            old3.delete();
        if( old4.exists() )
            old4.delete();
        if( old5.exists() )
            old5.delete();
        if( old6.exists() )
            old6.delete();
        
        try
        {
            
            if( controlClass.getProjectName() == null )
            {
                throw new Exception();
            }
            File nodesFile = new File("Files\\Projects\\" + controlClass.getProjectName() + "\\nodes.txt");
            if( nodesFile.exists() )
                nodesFile.delete();
            nodesFile.createNewFile();
        
            //save the data to the file
            controlClass.fileLoader.saveNodes(nodesFile, jCheckBox1.isSelected());
            /*
            //Save the node data
            FileWriter nodeWriter = new FileWriter(nodesFile);
            BufferedWriter nodeBWriter = new BufferedWriter(nodeWriter);
            
            //Write the number of nodes in the file
            String numNodes = new String(""+controlClass.nodes.length);
            nodeBWriter.write(numNodes);
            nodeBWriter.newLine();
            for( int i = 0; i< controlClass.nodes.length; i++)
            {
                //Save format:
                //Node Number, Network Location, Data Location Node Type, 
                //X-value, Y-value, Neighbor1, Neighbor1 delay, Neighbor2, ...
                String temp = new String(controlClass.nodes[i].getNumber()
                +" None None "+controlClass.nodes[i].getType()+" "
                + controlClass.nodes[i].getX() +" "
                + controlClass.nodes[i].getY() +" ");
                Vector v = controlClass.nodes[i].getNeighbors();
                for( int j = 0; j< v.size(); j++)
                {
                    //If you are supposed to preserve the network delays, then 
                    //save them along with the data
                    if( jCheckBox1.isSelected() )
                    {
                        temp = temp + (((Neighbor)v.elementAt(j)).getNumber()) 
                        +" "+
                        floatFormat.format(((Neighbor)v.elementAt(j)).getDelay())+" ";
                    }
                    
                    //Otherwise save 0 and set the internal number to 0
                    else
                    {
                        temp = temp + (((Neighbor)v.elementAt(j)).getNumber()) + " 0.0 ";
                        ((Neighbor)v.elementAt(j)).setDelay(0);
                    }
                }
                //System.out.println(temp);
                nodeBWriter.write(temp);
                nodeBWriter.newLine();
            }
            nodeBWriter.flush();*/
        }catch( IOException ex)
        {
            controlClass.showError("Topology Panel: Error: Couldn't save topology information to file!");
        }catch( Exception x)
        {
            controlClass.showError("Topology Panel: Error: No Project selected!  Could not save topology to file!");
        }
        
    }
    
     /**public method that tells this panel to sleep until further needed.  Sleep
     *means not to take up a lot of memory and certantly not to run any 
     *processes.
     */
    public void sleep()
    {
        
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {//GEN-BEGIN:initComponents
        jPanel1 = new javax.swing.JPanel();
        jPanel12 = new javax.swing.JPanel();
        jButton4 = new javax.swing.JButton();
        jPanel2 = new javax.swing.JPanel();
        jPanel3 = new javax.swing.JPanel();
        jCheckBox1 = new javax.swing.JCheckBox();
        jPanel4 = new javax.swing.JPanel();
        jPanel5 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jPanel8 = new javax.swing.JPanel();
        jButton3 = new javax.swing.JButton();
        jPanel11 = new javax.swing.JPanel();
        jPanel6 = new javax.swing.JPanel();
        jPanel7 = new javax.swing.JPanel();
        jPanel9 = new javax.swing.JPanel();
        jPanel10 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();

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

        jPanel1.setPreferredSize(new java.awt.Dimension(25, 25));
        jPanel1.setMaximumSize(new java.awt.Dimension(25, 25));
        jPanel1.setMinimumSize(new java.awt.Dimension(25, 25));
        jPanel12.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 5, 0));

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

        jPanel12.add(jButton4);

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

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

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

        jPanel3.setMaximumSize(new java.awt.Dimension(10, 10));
        jCheckBox1.setText("Model Network Delays");
        jPanel3.add(jCheckBox1);

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

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

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

        jPanel5.setPreferredSize(new java.awt.Dimension(50, 50));
        jPanel5.setMaximumSize(new java.awt.Dimension(50, 50));
        jPanel5.setMinimumSize(new java.awt.Dimension(50, 50));
        jLabel1.setText("Current File: None");
        jPanel5.add(jLabel1, java.awt.BorderLayout.CENTER);

        jPanel8.setLayout(new javax.swing.BoxLayout(jPanel8, javax.swing.BoxLayout.X_AXIS));

        jPanel8.setPreferredSize(new java.awt.Dimension(100, 50));
        jPanel8.setMinimumSize(new java.awt.Dimension(80, 50));
        jButton3.setText("Load File");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        jPanel8.add(jButton3);

        jPanel5.add(jPanel8, java.awt.BorderLayout.EAST);

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

        jPanel4.add(jPanel5, java.awt.BorderLayout.NORTH);

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

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

        jPanel7.add(jPanel9, java.awt.BorderLayout.WEST);

        jPanel7.add(jPanel10, java.awt.BorderLayout.EAST);

        jScrollPane1.setViewportView(jTextArea1);

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

        jPanel6.add(jPanel7, java.awt.BorderLayout.CENTER);

        jPanel4.add(jPanel6, java.awt.BorderLayout.CENTER);

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

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

    }//GEN-END:initComponents

    /**
     *Method for 'Save' clicked
     */
    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed
        this.save();
        controlClass.showError("Topology Panel: Topology Saved");
    }//GEN-LAST:event_jButton4ActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        //Open the file chooser
        int returnVal = fc.showOpenDialog(this.getParent());
        
        //Get the return file, if applicable bufferReader not initial
        try{
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                file = fc.getSelectedFile();
                reader = new FileReader(file);
                bReader = new BufferedReader(reader);
                jLabel1.setText("Current File: "+file.getPath());
            }
        }catch(IOException ex)
        {
            controlClass.showError(new String("Topology Panel: Error: Topology file would not open"));
        }
        
        //Read in the file
        try{
            //Control bool - requires the number of nodes before any specific node
            boolean numNodesFound = false;
            
            //Define the elemental patterns for an integer, decimal, and a string
            Pattern integerP = Pattern.compile("\\d+");
            Pattern decimalP = Pattern.compile("\\d+\\p{Punct}\\d+");
            Pattern stringP = Pattern.compile("[a-zA-Z]\\S+");
            
            //Display Message
            jTextArea1.setText("Below are the lines of the file that the system will use:\n");
            
            //Display all usable data
            String line = new String(bReader.readLine());
            while( line != null)
            {
                
                //See if it matches the pattern for a node representation in BRITE format
                nodeMatcher = nodePattern.matcher(line);
                edgeMatcher = edgePattern.matcher(line);
                numNodesM = numNodesP.matcher(line);
                //System.out.println(line);
                //See if it matches a line for a node
                if( line != null && nodeMatcher.matches() && numNodesFound == true )
                {
                    jTextArea1.append( new String(line + '\n'));
                    
                    //Matchers that will be used to parse the string
                    Matcher integerM = integerP.matcher(line);
                    Matcher stringM = stringP.matcher(line);

                    //parse out the 6 integers and string values and interpret them.
                    Node tempNode = new Node();
                    integerM.find();
                    int nodeIndex = Integer.parseInt(integerM.group()); //The index for the node that this lines numbers represent
                    tempNode.setNumber(nodeIndex);
                    integerM.find();
                    tempNode.setX(Integer.parseInt(integerM.group()));
                    integerM.find();
                    tempNode.setY(Integer.parseInt(integerM.group()));
                    integerM.find();
                    stringM.find();
                    tempNode.setType(stringM.group());
                    
                    //Add the node to the array
                    controlClass.nodes[nodeIndex] = tempNode;
                }
                
                //See if it matches the pattern for an edge representation in BRITE format
                else if( line != null && edgeMatcher.matches() )
                {
                    jTextArea1.append( new String(line + '\n'));
                    
                    //Matchers that will be used to parse the string
                    Matcher integerM = integerP.matcher(line);
                    Matcher decimalM = decimalP.matcher(line);
                    Matcher stringM = stringP.matcher(line);
                    
                    //Parse out the edge delay
                    integerM.find();
                    int edgeNumber = Integer.parseInt(integerM.group());
                    integerM.find();
                    int nodeFrom = Integer.parseInt(integerM.group());
                    integerM.find();
                    int nodeTo = Integer.parseInt(integerM.group());
                    decimalM.find();
                    decimalM.find();
                    double nodeDelay = Double.parseDouble(decimalM.group());

                    Neighbor temp = new Neighbor();
                    temp.setNumber(nodeTo);
                    temp.setDelay(nodeDelay);
                    controlClass.nodes[nodeFrom].addNeighbor(temp);
                    temp = new Neighbor();
                    temp.setNumber(nodeFrom);
                    temp.setDelay(nodeDelay);
                    controlClass.nodes[nodeTo].addNeighbor(temp);
                }
                
                //See if it matches a pattern for the number of nodes
                else if( line != null && numNodesM.find() && numNodesFound == false )
                {
                    //Matcher that will be used to find the number
                    Matcher integerM = integerP.matcher(line);

                    //Get the number of nodes
                    integerM.find();
                    int numNodes = Integer.parseInt(integerM.group());
                    controlClass.nodes = new Node[numNodes];
                    
                    //Mark the number as found
                    numNodesFound = true;
                    
                    System.out.println("Found the number of nodes...");
                }

                //Read in the next line
                line = bReader.readLine();
            }
        }catch(IOException ex)
        {
            controlClass.showError(new String("Topology Panel: Error: '"+file.getPath()+"' is an invalid file"));
        }
    }//GEN-LAST:event_jButton3ActionPerformed
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JCheckBox jCheckBox1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel10;
    private javax.swing.JPanel jPanel11;
    private javax.swing.JPanel jPanel12;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JPanel jPanel8;
    private javax.swing.JPanel jPanel9;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea jTextArea1;
    // End of variables declaration//GEN-END:variables
    
}
