// Import classes

import visad.*;
import visad.util.*;
import visad.java3d.DisplayImplJ3D;
import java.rmi.RemoteException;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;

public class partplot{

	// Class Variables
	private DisplayImplJ3D display;
	
	public partplot( int SampleCount,
					 float[] x_val,
					 float[] y_val,
					 float[] z_val,
					 float[] value_val )
	{
		try
		{
			// Create Variables
			RealType index = new RealType( "index" );
			RealType x = new RealType( "x" );
			RealType y = new RealType( "y" );
			RealType z = new RealType( "z" );
			RealType value = new RealType( "Value" );
			RealTupleType Points_tuple = new RealTupleType( x, y, z, value );
			
			// Create Function
			FunctionType func_index_points = new FunctionType( index, Points_tuple );
			
			// Create the Range/Domain Values
			Set domain_set = new Integer1DSet( index, SampleCount );
			float[][] point_vals = new float[][] {  x_val, y_val,
									  z_val, value_val };
			
			// Create Flat Field
			FlatField vals_ff = new FlatField( func_index_points, domain_set );
			vals_ff.setSamples( point_vals, false );
			
			// Create and configure display
			display = new DisplayImplJ3D( "Display1" );
			GraphicsModeControl dispGMC = (GraphicsModeControl) display.getGraphicsModeControl();
			dispGMC.setScaleEnable( true );
			dispGMC.setPointSize( 5.0f );
			
			display.addMap( new ScalarMap( x, Display.XAxis ) );
			display.addMap( new ScalarMap( y, Display.YAxis ) );
			display.addMap( new ScalarMap( z, Display.ZAxis ) );
			ScalarMap valueMap = new ScalarMap( value, Display.RGBA );
			display.addMap( valueMap );
			
			// Create Data Reference and connect it to everything
			DataReferenceImpl data_ref = new DataReferenceImpl( "data_ref" );
			data_ref.setData( vals_ff );
			display.addReference( data_ref );
		}
		catch( Exception e )
		{
			System.err.println( "EXCEPTION: " + e );
			e.printStackTrace();
			return;
		}       
	}
	
	public DisplayImplJ3D getDisplay()
	{
		return display;
	}
	
	public static void main (String[] args) 
	{
		// Checks to make sure there are enough arguments.
		if( args.length != 2 ){
			System.err.println( "Syntax: java partplot arg1 arg2" );
			System.err.println( "     arg1 = number of points" );
			System.err.println( "     arg2 = filename of datafile" );
			return;
		}

		// Assign the arguments to program variables.
		
		System.out.print( "Opening Data Files..." );
		int SampleCount = 0;
		String FileName;
		try{
			SampleCount = Integer.parseInt( args[0] );
			FileName = args[1];
		}
		catch( Exception e ){
			System.err.println( "EXCEPTION: " + e );
		}
		System.out.println( "done!" );

		// Read in the data from the data file
		System.out.print( "Reading " + SampleCount + " data values..." );
		int i;
		float[] x_val = new float[SampleCount];
		float[] y_val = new float[SampleCount];
		float[] z_val = new float[SampleCount];
		float[] value_val = new float[SampleCount];
		try{
			FileInputStream inputFile = new FileInputStream( args[1] );
			BufferedInputStream bufferData = 
											new BufferedInputStream( inputFile );
			DataInputStream dataIn = new DataInputStream( bufferData );

			for( i = 0; i < SampleCount; i++ ){
				x_val[i] = dataIn.readFloat();
				y_val[i] = dataIn.readFloat();
				z_val[i] = dataIn.readFloat();
				value_val[i] = dataIn.readFloat();
			}
		}
		catch( Exception e ){
			System.err.println( "EXCEPTION: " + e );
			e.printStackTrace();
		}
		System.out.println( "done!" );

		// Create the plot object
		System.out.print( "Creating plot..." );
		partplot particles = new partplot( SampleCount, 
										   x_val, y_val, 
										   z_val, value_val );
		
		// Create a Java window and attach the plot.
		JFrame jframe = new JFrame( "3d Particle Plot" );
		jframe.setSize(300, 300);
		jframe.getContentPane().add( particles.getDisplay().getComponent() );
		jframe.setVisible(true);
		System.out.println( "done!" );
	}
}