/*
 * nodeFileLoader.java
 *
 * Created on April 1, 2005, 12:54 PM
 */

package DDMT.core;
import javax.swing.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;//initial
import java.io.*;
import jade.domain.FIPAAgentManagement.*;
import DDMT.Nodes.*;
import DDMT.Agents.NodeAgent.AgentInterface;
import DDMT.Agents.ByteLoader;
import DDMT.Agents.NodeAgent;
import java.text.*;
import DDMT.core.MainPanel.ControlClass;
import java.awt.*;
import jade.lang.acl.ACLMessage;
import jade.core.AID;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.CompositeBehaviour;
import jade.core.behaviours.SequentialBehaviour;
import jade.lang.acl.MessageTemplate;
import jade.core.behaviours.Behaviour;
import java.util.Vector;

/**
 *
 * @author  jk3
 */
public class nodeFileLoader {

    //Pattern for a node definition
    //Node Number, Network Location, Data Location, Node Type, X-value, Y-value, Neighbor1, Neighbor1 delay, Neighbor2, ...
    private Pattern nodePattern = Pattern.compile("\\d+\\s\\S+\\s\\S+\\s\\S+\\s\\d+\\s\\d+\\s[\\d+\\s\\d+\\p{Punct}\\d+\\s]*");
    private Matcher nodeMatcher;
    
    //The standard group of patterns from the other panels
    private Pattern integerP = Pattern.compile("\\d+");
    private Pattern doubleP = Pattern.compile("\\d+\\p{Punct}\\d+");
    private Pattern stringP = Pattern.compile("\\S+\\s");
    private Pattern alphaStringP = Pattern.compile("[a-zA-Z]\\S*");
    private Pattern neighborP = Pattern.compile("\\s\\d+\\s\\d+\\p{Punct}\\d+");
    private Pattern fileP = Pattern.compile("\\S+\\s\\S+");
    private Pattern firstP = Pattern.compile("\\A(\\S+)");
    private Pattern nextP = Pattern.compile("\\s(\\S+)");
    private Pattern lastP = Pattern.compile("\\S+\\Z");
    private Matcher fileM;
    private Matcher firstM;
    private Matcher nextM;
    private Matcher lastM;
    private Matcher integerM;
    private Matcher doubleM;
    private Matcher stringM;
    private Matcher alphaStringM;
    private Matcher neighborM;
    
    //Pattern for outputting decimal numbers
    private String floatPattern = new String("####0.0#######");
    private DecimalFormat floatFormat = new DecimalFormat(floatPattern);
    
    //The control class for the loader
    ControlClass controlClass;
    
    /**
     *Create a new nodeFileLoader object
     */
    public nodeFileLoader(ControlClass cClass)
    {
        controlClass = cClass;
    }
    
    
    /**
     *Method to load all the node data from a file
     */
    public void loadNodes(File nodesFile) throws Exception
    {
        FileReader fileReader = new FileReader(nodesFile);
        BufferedReader bReader = new BufferedReader(fileReader);
        //Read the number of nodes

        String line = bReader.readLine();
        if( line == null )
        {
            throw new Exception();
        }
        controlClass.nodes = new Node[Integer.parseInt(line)];
        line = bReader.readLine();

        //Loop for each line read.
        int i = 0;
        while( line != null )
        {
            nodeMatcher = nodePattern.matcher(line);
            if( nodeMatcher.matches() )
            {
                //Set up the matchers
                integerM = integerP.matcher(line);
                doubleM = doubleP.matcher(line);
                alphaStringM = alphaStringP.matcher(line);
                neighborM = neighborP.matcher(line);

                //Read in the node.
                Node node = new Node();
                integerM.find();
                node.setNumber(Integer.parseInt(integerM.group()));
                alphaStringM.find();
                node.setNetworkLocation(alphaStringM.group());
                alphaStringM.find();
                node.setDataLocation(alphaStringM.group());
                System.out.println(node.getDataLocation());
                //System.out.println(node.getDataLocation());
                alphaStringM.find();
                //System.out.println(alphaStringM.group());
                node.setType(alphaStringM.group());
                integerM.find();
                node.setX(Integer.parseInt(integerM.group()));
                integerM.find();
                node.setY(Integer.parseInt(integerM.group()));

                //Load the neighbors
                while( neighborM.find() )
                {
                    String neighbor = new String( neighborM.group() );
                    integerM = integerP.matcher(neighbor);
                    doubleM = doubleP.matcher(neighbor);
                    Neighbor nodeNeighbor = new Neighbor();
                    integerM.find();
                    nodeNeighbor.setNumber(Integer.parseInt(integerM.group()));
                    doubleM.find();
                    nodeNeighbor.setDelay(Double.parseDouble(doubleM.group()));
                    node.addNeighbor(nodeNeighbor);

                }
                //Add node to nodes list
                controlClass.nodes[i] = node;
                //System.out.println(((Vector)node.getNeighbors()).size());
                i++;
            }
            line = bReader.readLine();
        }

        //Close the files
        bReader.close();
        fileReader.close();
    }
    
    public void saveNodes(File nodesFile) throws IOException
    {
        saveNodes(nodesFile, true);
    }
    public void saveNodes(File nodesFile , boolean saveDelays) throws IOException
    {
        //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 = controlClass.nodes[i].getNumber()+
                " "+controlClass.nodes[i].getNetworkLocation()+
                " "+controlClass.nodes[i].getDataLocation()+
                " "+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( saveDelays )
                    {
                        temp = temp + (((Neighbor)v.elementAt(j)).getNumber()) 
                        +" "+
                        floatFormat.format(((Neighbor)v.elementAt(j)).getDelay())+" ";
                    }
                    
                    //Otherwise save 1 and set the internal number to 1
                    else
                    {
                        temp = temp + (((Neighbor)v.elementAt(j)).getNumber()) + " 1.0 ";
                        ((Neighbor)v.elementAt(j)).setDelay(1);
                    }
                }
                //System.out.println(temp);
                nodeBWriter.write(temp);
                nodeBWriter.newLine();
            }
            nodeBWriter.flush();
    }
    
}
