package animation2D;
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;

import javax.swing.JButton;
import javax.swing.JPanel;

import visad.AnimationControl;
import visad.DataImpl;
import visad.DataReference;
import visad.DataReferenceImpl;
import visad.FieldImpl;
import visad.FlatField;
import visad.Gridded3DSet;
import visad.Gridded2DSet;
import visad.Display;
import visad.DisplayImpl;
import visad.GraphicsModeControl;
import visad.data.netcdf.Plain;
import visad.data.mcidas.BaseMapAdapter;
import visad.java3d.DisplayRendererJ3D;
import visad.ConstantMap;
import visad.ScalarMap;
import visad.ProjectionControl;
import java.util.Vector;

import auto3DVisad.MyDataUtility;
import visad.DataRenderer;
import visad.DataDisplayLink;

public class Animation2DVisad extends Applet 
{
    DataImpl image_sequence = null;
    BaseMapAdapter baseMapAdapter;
    String url = "";
    String file = "";
    String varname = "";
    String mapFile = "";
    
    public void init()
    {
        try
        {
            //debug
            System.out.println("Debug mode");
            varname = "dms510";
            mapFile = "C:/OUTLSUPW";
            file = "C:/0f64af9404ddffcc0b8bedbdf264d061.nc";

        }
        catch(Exception ex)
        {
            System.out.println(ex);
        }
    }
    
    public void start()
    {
        getData();
        drawData();
    }
    
    public void getData()
    {
        try
        {         
            Plain plain = new Plain();
            
            //open netcdf file
            if(url != null && !url.equals(""))
                image_sequence = plain.open(new URL(url));
            else
                image_sequence = plain.open(file);
            
            //open OUTL* file
            if (mapFile.indexOf("://") > 0)            
            	baseMapAdapter = new BaseMapAdapter(new URL(mapFile));
        
            else
                baseMapAdapter = new BaseMapAdapter(mapFile);
            
            if(image_sequence == null)
                System.out.println("image_sequence is null");
            
            if(baseMapAdapter == null)
                System.out.println("baseMapAdapter is null");
        }
        catch(Exception ex)
        {
            System.out.println(ex);
        }
    }
    
    public void drawData()
    {
        try
        {  
            //create a Display using Java3D        
            DisplayImpl display =
MyDataUtility.makeSimpleDisplay(image_sequence);
            GraphicsModeControl dispGMC = (GraphicsModeControl)
display.getGraphicsModeControl();
            dispGMC.setScaleEnable(true);
            
            ScalarMap latMap = null, lonMap = null, varMap = null;
            Vector mapList = display.getMapVector();
            for(int idx = 0 ; idx < mapList.size() ; idx++)
            {
                ScalarMap tempMap = (ScalarMap)mapList.get(idx);
                if(tempMap.getScalarName().equals("Latitude"))
                    latMap = tempMap;
                else if(tempMap.getScalarName().equals("Longitude"))
                    lonMap = tempMap;
                else if(tempMap.getScalarName().equals(varname))
                    varMap = tempMap;
            }
                       
            //varMap
            if(varMap.getDisplayScalar() == Display.IsoContour)
            {
                ScalarMap varColorMap = new
ScalarMap(varMap.getScalar(), Display.RGB);                    
                display.addMap(varColorMap);
            }
            else
            {
                ScalarMap varIsoMap = new
ScalarMap(varMap.getScalar(), Display.IsoContour);                    
                display.addMap(varIsoMap);
            }
            

/////////////////////////////////////////////////////////////Debug
            
            //Data from DisplayImpl             
            /*Vector list = display.getRendererVector();
            for(int idx = 0 ; idx < list.size() ; idx++)
            {
                DataRenderer temp_red = (DataRenderer)list.get(idx);
                DataDisplayLink[] displaylink = temp_red.getLinks();
                for(int jdx = 0 ; jdx < displaylink.length ; jdx++)
                {
                    DataReference data_ref =
displaylink[jdx].getDataReference();
                    FieldImpl temp_field =
(FieldImpl)data_ref.getData();
                    
                    for(int zdx = 0; zdx < temp_field.getLength() ;
zdx++)
                    {
                        FieldImpl data_field =
(FieldImpl)temp_field.getSample(zdx);
                        
                        double[][] dd = data_field.getValues();
                        for(int ldx = 0 ; ldx < dd.length ; ldx++)
                        {
                            for(int mdx = 0 ; mdx < dd[ldx].length ;
mdx++)
                            {
                                if(mdx % 4 == 0)
                                    System.out.println(dd[ldx][mdx] +
"\t");
                            }
                            
                            System.out.println("");
                        }
                    }                    
                }                
            }*/

/////////////////////////////////////////////////////////////Debug
            
            //set lon & lat range
            float[] hi = null;
            float[] low = null;            
            double lonRange[] = new double[2];
            double latRange[] = new double[2];
            FieldImpl temp_field = (FieldImpl) image_sequence;
            FlatField image_field =
(FlatField)temp_field.getSample(0);                        
            int numArray = image_field.getDomainDimension();
            if(numArray == 2)
            {
                Gridded2DSet set = (Gridded2DSet)
image_field.getDomainSet();
                hi = set.getHi();
                low = set.getLow();
            }
            else if(numArray == 3)
            {
                Gridded3DSet set = (Gridded3DSet)
image_field.getDomainSet();
                hi = set.getHi();
                low = set.getLow();
            }
            else
            {                
            }
            lonRange[0] = low[0];
            lonRange[1] = hi[0];
            latRange[0] = low[1];
            latRange[1] = hi[1];
            lonMap.setRange(lonRange[0], lonRange[1]);
            latMap.setRange(latRange[0], latRange[1]);            


/////////////////////////////////////////////////////////////Debug
            
            //Data from Netcdf file
            /*FieldImpl temp_field = (FieldImpl) image_sequence;
            for(int zdx = 0; zdx < temp_field.getLength() ; zdx++)
            {
                FieldImpl data_field =
(FieldImpl)temp_field.getSample(zdx);
                
                double[][] dd = data_field.getValues();
                for(int idx = 0 ; idx < dd.length ; idx++)
                {
                    for(int jdx = 0 ; jdx < dd[idx].length ; jdx++)
                    {
                        if(jdx % 4 == 0)
                            System.out.println(dd[idx][jdx] + "\t");
                    }
                    
                    System.out.println("");
                }
            }*/

/////////////////////////////////////////////////////////////Debug
            
            DataReference maplinesRef = new
DataReferenceImpl("MapLines");
            enableClipping(display, dispGMC, true);
            maplinesRef.setData(baseMapAdapter.getData());
            
            ConstantMap[] maplinesConstantMap = new ConstantMap[5];
            maplinesConstantMap[0] = new ConstantMap(1.,
Display.Blue);
            maplinesConstantMap[1] = new ConstantMap(1., Display.Red);
            maplinesConstantMap[2] = new ConstantMap(1.,
Display.Green);
            maplinesConstantMap[3] = new ConstantMap(1.001,
Display.Radius); // just above the image
            maplinesConstantMap[4] = new ConstantMap(-1.0f,
Display.ZAxis);
            display.addReference(maplinesRef, maplinesConstantMap);
            
            ProjectionControl projCont =
display.getProjectionControl();
            double[] latvalue = latMap.getRange();
            double[] lonvalue = lonMap.getRange();
            double latStart = latvalue[0];
            double latEnd = latvalue[latvalue.length - 1];            
            double lonStart = lonvalue[0];
            double lonEnd = lonvalue[lonvalue.length - 1];
            
            if(!Double.isNaN(latStart) && !Double.isNaN(latEnd) &&
!Double.isNaN(lonStart) && !Double.isNaN(lonEnd))
            {
                if(latStart != Double.NaN && latEnd != Double.NaN &&
lonStart != Double.NaN &&lonEnd != Double.NaN)
                {
                    if((latEnd - latStart) <= (lonEnd - lonStart))
                    {
                        double[] aspect = new double[]{1, (latEnd -
latStart) / (lonEnd - lonStart), 1};                
                        projCont.setAspect(aspect);
                    }
                    else
                    {                
                        double[] aspect = new double[]{(lonEnd -
lonStart) / (latEnd - latStart), 1, 1};
                        projCont.setAspect(aspect);
                    }
                }
            }
            
            //start animation
            final AnimationControl control = (AnimationControl)
display.getControl(AnimationControl.class);
            
            //Create Button control Animation
            JPanel southPanel = new JPanel();
            southPanel.setLayout(new FlowLayout());
            
            JButton btnPlay = new JButton("Play");
            btnPlay.addActionListener(new ActionListener() {  
                public void actionPerformed(ActionEvent e) {
                    try
                    {
                        control.setOn(true);                        
                    }
                    catch(Exception ex)
                    {                    
                    }
                }
            });        
            southPanel.add(btnPlay);
                    
            JButton btnStop = new JButton("Stop");        
            btnStop.addActionListener(new ActionListener() {  
                public void actionPerformed(ActionEvent e) {
                    try
                    {                       
                        control.setOn(false);                        
                    }
                    catch(Exception ex)
                    {                    
                    }
                }
            });        
            southPanel.add(btnStop);                
                    
            JButton btnNext = new JButton("Next");//previous
            btnNext.addActionListener(new ActionListener() {  
                public void actionPerformed(ActionEvent e) {
                    try
                    {
                        if(control.getOn())
                            control.setOn(false);
                        
                        control.setCurrent(control.getCurrent() + 1);
                    
                    }
                    catch(Exception ex)
                    {                    
                    }
                }
            });        
            southPanel.add(btnNext);
            
            JButton btnPrevious = new JButton("Previous");
            btnPrevious.addActionListener(new ActionListener() {  
                public void actionPerformed(ActionEvent e) {
                    try
                    {
                        if(control.getOn())
                            control.setOn(false);
                        
                        control.setCurrent(control.getCurrent() - 1);
                    
                    }
                    catch(Exception ex)
                    {                    
                    }
                }
            });        
            southPanel.add(btnPrevious);                        
            
            //debug
            //setSize(800, 600);
            setLayout(new BorderLayout());            
            add(display.getComponent(), BorderLayout.CENTER);

            add(southPanel, BorderLayout.SOUTH);
        }
        catch(Exception ex)
        {
            System.out.println(ex);
        }
    }
    
    /*

**********************************************************************
     *
     *	Function Name :
     *		enableClipping()
     *
     *	Description :
     * 		Enable clipping of data at the box edges
     *
     *	Arguments :
     *		display : VisAD class for display implementations
     *		dispGMC : VisAD class for controlling various mode settings for
rendering.
     *     	clip : true to turn clipping on, otherwise off
     *
     *	Example :
     * 		enableClipping(display, dispGMC, true);
     * 
     * 	Restriction :
     * 		display.getDisplayRenderer() must be DisplayRendererJ3D
     * 
     * 	Return :
     * 		Null value 
     *
     * 	Date :
     *		05/17/2006
     *

**********************************************************************
     */
    public void enableClipping(DisplayImpl display, GraphicsModeControl
dispGMC, boolean clip) 
    {     
        DisplayRendererJ3D dr = (DisplayRendererJ3D)
display.getDisplayRenderer();
        
        try 
        {
            dr.setClip(0, clip,  1.0f,  0.0f,  0.0f, -1.001f);
            dr.setClip(1, clip, -1.0f,  0.0f,  0.0f, -1.001f);
            dr.setClip(2, clip,  0.0f,  1.0f,  0.0f, -1.001f);
            dr.setClip(3, clip,  0.0f, -1.0f,  0.0f, -1.001f);
    
        }
        catch (Exception e) 
        {
            System.err.println("Couldn't set clipping " + e);    
        }        
    }        
}
