package mdsServerDomain;

import java.io.*;
import javax.swing.tree.DefaultTreeModel;

/** Connects to MDSplus database and constructs the experiment tree */
public class MDSTree extends DefaultTreeModel
{
    private DataServerFacade database;

    public MDSTree(DataServerFacade _database, MDSTreeNode _top)
    {
	super(_top);
        database = _database;
    }

    /** Recursively create an experiment tree from the MDSPlus server
        @throws IOException If not connected to server or experiment not opened */
    public void getTree() throws IOException
    {
        String experiment;

        if ( database != null && database.isConnected() && database.isOpen() )
        {
            experiment = database.getExperiment();

            MDSTreeNode top = getSubTree("\\\\" + experiment.toUpperCase() + "::TOP", "TOP", MDSTreeNode.TYPE_TOP );
	    setRoot(top);
        }
        else
        {
            throw new IOException( "Database not open" );
        }
    }

    /** Part of the recursion algorithim used to create the tree
    @param path The path to the parent node of the sub-tree
    @param nodeName The name of this node
    @param type The node type
    @return The newly-created parent node of this sub-tree
    @throws IOException From call to getSubTreeList
    */
    private MDSTreeNode getSubTree(String path, String nodeName, int type) throws IOException
    {
        MDSTreeNode out;
        String nodelist[];
        int i;

        out = new MDSTreeNode( nodeName, type );

	// Process MDSplus "member" nodes
        nodelist = getSubTreeList( path + ":*" );
        if ( nodelist != null )
        {
            for ( i = 0; i < nodelist.length; i ++ )
            {
                out.add(getSubTree(path + ":" + nodelist[i], nodelist[i], MDSTreeNode.TYPE_MEMBER ) );
            }
        }

	// Process MDSplus "child" nodes
        nodelist = getSubTreeList( path + ".*" );
        if ( nodelist != null )
        {
            for ( i = 0; i < nodelist.length; i ++ )
            {
                out.add(getSubTree(path + "." + nodelist[i], nodelist[i], MDSTreeNode.TYPE_CHILD ) );
            }
        }

        return out;
    }

    /**
    Gets a list of all member and child nodes of a node
    @param path The path to the parent node
    @return A list of the member and child nodes
    @throws IOException If there is an error communicating with the MDSPlus server
    */
    private String[] getSubTreeList(String path) throws IOException
    {
        MDSDescriptor result;
        int nodes;
        int i;
        String out[];
        String expr;

        expr = "GETNCI(\"" + path + "\",\"NODE_NAME\")";
        result = database.evaluate( expr );

        if ( result.getDtype() == MDSDescriptor.DTYPE_CSTRING )
        {
            if (result.getCstringData().endsWith("Node Not Found"))
	    { //There are no nodes below this path
                return null;
            }

            if (result.getCstringData().substring( 0, 4 ).equals( "Tree" ))
	    { //Some other sort of error: throw exception
                throw new IOException( "GETNCI Error: " +
                                     result.getCstringData() );
            }

            nodes = result.getCstringData().length() / 12;
            out = new String[nodes];
            for ( i = 0; i < nodes; i ++ )
            {
                out[i] = result.getCstringData().substring( 12*i,
                12*(i+1) ).trim();
            }
        }
        else
        { // Didn't get correct format from message
            throw new IOException( "GETNCI Error: " +
                             "Incorrect format returned: " +
                             result.getDtype() );
        }
        return out;
    }
}
