package iDSS.gView;

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.*;
import java.io.*;
import java.beans.*;
import javax.imageio.*;

import iDSS.*;
import iDSS.gridDisp.*;
import iDSS.disp.*;
import iDSS.utils.*;
import iDSS.grids.*;
import iDSS.tables.*;





public class GridViewControl extends DisplayFrame implements ActionListener,PropertyChangeListener {


    private JTable gridsTable;
    private JButton drawButton,runButton,newButton,disposeButton,describeButton;
    private JComboBox dataCategoryCombo;

    public static final int INSTANT = 1;
    public static final int SUMMARY = 2;
    public static final int HISTORY = 3;
    private int gridsType;

    private boolean ALLOW_ROW_SELECTION = true;
    private Vector gridsListVector;

    private String currentFileName,currentName;
    //private File currentFile;
    private Vector currentRow;

    private final int MINIMUM_IMAGE_SIZE = IDSSAppConstants.MINIMUM_IMAGE_SIZE_FOR_ANIM;


    public GridViewControl(int type,String title) {

        super(title,false,true,false,true,null);

        gridsType = type;

        gridsListVector = new Vector();


        Vector columnNames = new Vector();
        //columnNames.add("Grid Name");
        columnNames.add("Grid File Name");

        Vector row = new Vector();

/**
        Enumeration gridFiles = gridsListVector.keys();

        while(gridFiles.hasMoreElements()) {

            Vector oneRow = new Vector();
            String fileName = (String) gridFiles.nextElement();
            Grid aGrid = (Grid) gridsListVector.get(fileName);
            String gridName = aGrid.getName();
            oneRow.add(gridName);
            oneRow.add(fileName);
            row.add(oneRow);

        } //while(gridFiles.hasMoreElements())
**/

        GeneralTableModel tm = new GeneralTableModel(row,columnNames);

        gridsTable = new JTable(tm);
        gridsTable.setPreferredScrollableViewportSize(new Dimension(300,100));

        JScrollPane gridsTableScrollPane = new JScrollPane(gridsTable,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);


        JPanel gridsTablePanel = new JPanel();
        gridsTablePanel.setBorder(BorderFactory.createTitledBorder("Grids for viewing"));

        gridsTablePanel.setLayout(new BoxLayout(gridsTablePanel,BoxLayout.X_AXIS));
        gridsTablePanel.add(gridsTableScrollPane);

        drawButton = new JButton(IDSSAppConstants.drawButtonText);
        drawButton.setActionCommand(IDSSAppConstants.drawButtonCommand);
        drawButton.addActionListener(this);
        drawButton.setEnabled(false);

        runButton = new JButton(IDSSAppConstants.runButtonText);
        runButton.setActionCommand(IDSSAppConstants.runButtonCommand);
        runButton.addActionListener(this);
        runButton.setEnabled(false);

        newButton = new JButton(IDSSAppConstants.newButtonText);
        newButton.setActionCommand(IDSSAppConstants.newButtonCommand);
        newButton.addActionListener(this);

        disposeButton = new JButton(IDSSAppConstants.disposeButtonText);
        disposeButton.setActionCommand(IDSSAppConstants.disposeButtonCommand);
        disposeButton.addActionListener(this);
        disposeButton.setEnabled(false);

        describeButton = new JButton(IDSSAppConstants.describeButtonText);
        describeButton.setActionCommand(IDSSAppConstants.describeButtonCommand);
        describeButton.addActionListener(this);
        describeButton.setEnabled(false);


        if(type == SUMMARY) {
            Vector parameters = GridCell.getParametersVector();
            dataCategoryCombo = new JComboBox(parameters);
        } //if(type == SUMMARY)

        else if (type == HISTORY) {

            Vector parameters = GridCell.getParametersVector();
            dataCategoryCombo = new JComboBox(parameters);

        } //else if (type == HISTORY)


        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new BoxLayout(buttonPanel,BoxLayout.X_AXIS));
        //buttonPanel.add(drawButton);
        buttonPanel.add(describeButton);
        buttonPanel.add(runButton);
        buttonPanel.add(newButton);
        buttonPanel.add(disposeButton);

        if((type == SUMMARY) || (type == HISTORY))
            buttonPanel.add(dataCategoryCombo);

        getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.Y_AXIS));
        getContentPane().add(gridsTablePanel);
        getContentPane().add(buttonPanel);

        setBackground(Color.lightGray);
        pack();
        setVisible(true);


      //Detecting row selection

      if (ALLOW_ROW_SELECTION) { // true by default
          ListSelectionModel rowSM = gridsTable.getSelectionModel();
          rowSM.addListSelectionListener(new ListSelectionListener() {
              public void valueChanged(ListSelectionEvent e) {
                  //Ignore extra messages.
                  if (e.getValueIsAdjusting()) return;

                  ListSelectionModel lsm = (ListSelectionModel)e.getSource();
                  if (lsm.isSelectionEmpty()) {
                      System.out.println("No rows are selected.");
                      drawButton.setEnabled(false);
                      disposeButton.setEnabled(false);
                      describeButton.setEnabled(false);

                  } else {
                      int selectedRow = lsm.getMinSelectionIndex();
                      System.out.println("Row " + selectedRow
                                       + " is now selected.");

                      drawButton.setEnabled(true);
                      disposeButton.setEnabled(true);
                      describeButton.setEnabled(true);

                      currentFileName = (String) gridsTable.getValueAt(selectedRow,0);

                      //currentFile = new File(currentFileName);

                      //currentName = (String) gridsTable.getValueAt(selectedRow,0);

                      currentRow = new Vector();
                      //currentRow.add(currentName);

                      currentRow.add(currentFileName);
                    

                  }
              }
          });
      } else {
          gridsTable.setRowSelectionAllowed(false);
      }




    } //public GridViewControl(int type)





    public void actionPerformed(ActionEvent ae) {


        if(ae.getActionCommand().equals(IDSSAppConstants.describeButtonCommand)) {

            File aFile = new File(currentFileName);
            Grid aGrid = null;

            if (gridsType == INSTANT) {

                aGrid = (Grid) Grid.readGridObject(aFile);
            }

            else if (gridsType == SUMMARY) {

                String dataCategory = (String) dataCategoryCombo.getSelectedItem();

                Grid2 aGrid2 = (Grid2) Grid2.readGrid2Object(aFile);
                aGrid = aGrid2.getGrid(dataCategory);

            }


            if(aGrid != null) {
                describeGrid(aGrid);
            }


        } //if(ae.getActionCommand().equals(IDSSAppConstants.describeButtonCommand))


        else if(ae.getActionCommand().equals(IDSSAppConstants.newButtonCommand)) {

            getNewGrid();

        } //if(ae.getActionCommand().equals(IDSSAppConstants.newButtonCommand))


        else if(ae.getActionCommand().equals(IDSSAppConstants.disposeButtonCommand)) {

            removeFromGrids();

        } //else if(ae.getActionCommand().equals(IDSSAppConstants.disposeButtonCommand))

        else if(ae.getActionCommand().equals(IDSSAppConstants.runButtonCommand)) {

            runAnimation();

        } //else if(ae.getActionCommand().equals(IDSSAppConstants.runButtonCommand))


    } //public void actionPerformed(ActionEvent ae)





    private SurfaceColor getDefaultSC() {

        Vector z = new Vector();
        Vector r = new Vector();
        Vector g = new Vector();
        Vector b = new Vector();

        z.add(new Double(0));
        z.add(new Double(1.8));
        z.add(new Double(3.6));
        z.add(new Double(5.4));
        z.add(new Double(7.2));

        r.add(new Double(0));
        r.add(new Double(.2));
        r.add(new Double(1));
        r.add(new Double(.2));
        r.add(new Double(0));

        g.add(new Double(.25));
        g.add(new Double(0));
        g.add(new Double(0));
        g.add(new Double(0));
        g.add(new Double(0));

        b.add(new Double(0));
        b.add(new Double(0.25));
        b.add(new Double(0.50));
        b.add(new Double(0.75));
        b.add(new Double(1.0));

        SurfaceColor sc = new SurfaceColor("Grids Animation",z,r,g,b);
        return sc;

    } //private SurfaceColor getDefaultSC()



















    private void runAnimation() {


        Vector gridsVector = new Vector();

        //Enumeration grids = gridsListVector.elements();

        //GeneralTableModel tm = (GeneralTableModel) gridsTable.getModel();
        //int numberOfRows = tm.getNumberOfRows();

        if (gridsType == INSTANT) {

            double zMin = 9999;
            double zMax = -9999;

            for(int i=0;i<gridsListVector.size();i++) {

                File aFile = (File)gridsListVector.elementAt(i);
                Grid aGrid = (Grid) Grid.readGridObject(aFile);

                zMin = Math.min(zMin,aGrid.getZMin());
                zMax = Math.max(zMax,aGrid.getZMax());

            } //for(int i=0;i<gridsListVector.size();i++)

            SurfaceColor scForFlood = new SurfaceColor("Flood Grids",zMin,zMax,SurfaceColor.FLOOD);


            for(int i=0;i<gridsListVector.size();i++) {

                File aFile = (File)gridsListVector.elementAt(i);
                Grid aGrid = (Grid) Grid.readGridObject(aFile);

                Vector oneRow = writeImgFiles(scForFlood,aGrid);
                gridsVector.add(oneRow);

            }//for(int i=0;i<gridsListVector.size();i++)

            addAnimationToDesktop("Frames of instant flood grids",gridsVector,scForFlood);

        } //if (gridsType == INSTANT)


        else if (gridsType == SUMMARY) {

            String dataCategory = (String) dataCategoryCombo.getSelectedItem();
            double zMin = 9999;
            double zMax = -9999;

            //System.out.println("gridsType = " + gridsType +", dataCategory = " + dataCategory);

            if(dataCategory == IDSSAppConstants.highestDepthOfFlooding) {

                for(int i=0;i<gridsListVector.size();i++) {

                    //System.out.println("determining zMin and zMax");

                    File aFile = (File)gridsListVector.elementAt(i);
                    Grid2 aGrid2 = (Grid2) Grid2.readGrid2Object(aFile);
                    Grid aGrid = aGrid2.getGrid(dataCategory);

                    zMin = Math.min(zMin,aGrid.getZMin());
                    zMax = Math.max(zMax,aGrid.getZMax());

                    //System.out.println("zMin,zMax = " + zMin +"," + zMax);

                }//for(int i=0;i<gridsListVector.size();i++)

            } //if(dataCategory == IDSSAppConstants.highestDepthOfFlooding)

            SurfaceColor scForFlood = new SurfaceColor("Flood Grids",zMin,zMax,SurfaceColor.FLOOD);
            SurfaceColor scForProbability = new SurfaceColor("Probability Grids",0,1,SurfaceColor.DEM);
            double d = 365.0*24*60.0*60.0*1000.0;
            SurfaceColor scForTime = new SurfaceColor("Time Length",SurfaceColor.TIMECOLORSCHEMEUPTOAYEAR);

            for(int i=0;i<gridsListVector.size();i++) {

                File aFile = (File)gridsListVector.elementAt(i);
                Grid2 aGrid2 = (Grid2) Grid2.readGrid2Object(aFile);
                Grid aGrid = aGrid2.getGrid(dataCategory);

                Vector oneRow = null;


                if(dataCategory == IDSSAppConstants.highestDepthOfFlooding) {
                    //oneRow.add(aGrid.getImage(scForFlood));
                    oneRow = writeImgFiles(scForFlood,aGrid);

                }



                else if(dataCategory == IDSSAppConstants.minimumProbabilityOfSurvival) {
                    //oneRow.add(aGrid.getImage(scForProbability));
                    oneRow = writeImgFiles(scForProbability,aGrid);

                }

                else {
                    //oneRow.add(aGrid.getImage(scForTime));
                    oneRow = writeImgFiles(scForTime,aGrid);
                }

                gridsVector.add(oneRow);

            }//for(int i=0;i<gridsListVector.size();i++)



            if(dataCategory == IDSSAppConstants.highestDepthOfFlooding)
                addAnimationToDesktop("Frames of yearly summary",gridsVector,scForFlood);
            else if(dataCategory == IDSSAppConstants.minimumProbabilityOfSurvival)
                addAnimationToDesktop("Frames of yearly summary",gridsVector,scForProbability);
            else
                addAnimationToDesktop("Frames of yearly summary",gridsVector,scForTime);


        } //else if (gridsType == SUMMARY)


        else if (gridsType == HISTORY) {

            String dataCategory = (String) dataCategoryCombo.getSelectedItem();
            SurfaceColor sc = getDefaultSC();

            for(int i=0;i<gridsListVector.size();i++) {

                File aFile = (File)gridsListVector.elementAt(i);
                LCGrid2 lcGrid2 = (LCGrid2) LCGrid2.readLCGrid2Object(aFile);

                Enumeration years = lcGrid2.getYears();

                if(years != null) {

                    while(years.hasMoreElements()) {

                        Integer aYear = (Integer) years.nextElement();
                        Grid aGrid = lcGrid2.getGrid(dataCategory,aYear.intValue());

                        Vector oneRow = writeImgFiles(sc,aGrid);
                        gridsVector.add(oneRow);


                        //Vector oneRow = new Vector();
                        //oneRow.add(aGrid.getImage(sc));
                        //oneRow.add(aGrid.getName());
                        //gridsVector.add(oneRow);

                    } //while(years.hasMoreElements())

                } //if(years != null)

            }//for(int i=0;i<gridsListVector.size();i++)

        } //else if (gridsType == HISTORY)


    } //private void runAnimation()







    private Vector writeImgFiles(SurfaceColor sc,Grid aGrid) {

        BufferedImage bi = aGrid.getImage(sc);
        BufferedImage bi2 = null;

        if ((bi.getWidth() < MINIMUM_IMAGE_SIZE) && (bi.getHeight() < MINIMUM_IMAGE_SIZE)) {

            int longSide = Math.max(bi.getWidth(),bi.getHeight());
            int ratio = MINIMUM_IMAGE_SIZE / longSide;

            bi2 = new BufferedImage (bi.getWidth()*ratio,bi.getHeight()*ratio,BufferedImage.TYPE_INT_RGB);
            Graphics g2 = bi2.getGraphics();
            g2.drawImage(bi,0,0,bi2.getWidth(),bi2.getHeight(),0,0,bi.getWidth(),bi.getHeight(),null);

        }

        else {
            bi2 = bi;
        }


        File tempDir = new File(IDSSAppConstants.tempDir);
        if(!tempDir.exists())
            tempDir.mkdirs();

        //File tempOutFile = new File(tempDir,FileNameDialog.getTempFileName());
        File tempOutFile = new File(tempDir,FileNameDialog.getTempImgFileName());

        tempOutFile.deleteOnExit();

        if(tempOutFile.exists())
            tempOutFile.delete();


        try {
            ImageIO.write(bi2, "png", tempOutFile);
        }

        catch(javax.imageio.IIOException ie) {

            System.out.println("GridViewColtrol.writeImgFiles(), " + ie.toString());

        } //catch(javax.imageio.IIOException ie)


        Vector oneRow = new Vector();
        oneRow.add(tempOutFile);
        oneRow.add(aGrid.getName());

        return oneRow;

    } //private Vector writeImgFiles(SurfaceColor sc,Grid aGrid)























    private void addAnimationToDesktop(String animTitle,Vector gridsVector,SurfaceColor sc) {

        AnimationFrame animFrame = new AnimationFrame (animTitle,gridsVector);

        animFrame.removePropertyChangeListener(this);
        animFrame.addPropertyChangeListener(this);

        addToDesktop(animFrame);

        //This is to solve a bug thst JSliders don't appear in JInternalFrame
        Dimension dim = animFrame.getSize();
        //if (dim.width > 5) {
            dim.width = dim.width+100;
            animFrame.setSize(dim.width,dim.height);
        //}
        //This is to solve a bug thst JSliders don't appear in JInternalFrame - end


        ImageDisplay legendFrame = new ImageDisplay("Legend",sc.getLegendWidth(),
                                        sc.getLegendHeight());

        addToDesktop(legendFrame);
        sc.drawLegend(legendFrame);


    } //private void addAnimationToDesktop(SurfaceColor sc)









    private void drawSummaryGrid(Grid2 aGrid2) {

        String dataCategory = (String) dataCategoryCombo.getSelectedItem();
        Grid currentGrid = aGrid2.getGrid(dataCategory);
        drawGrid(currentGrid);

    } //private void drawSummaryGrid(Grid currentGrid)








    private void drawGrid(Grid currentGrid) {

        if (!currentGrid.isRead()) {
            currentGrid.read();
        }


        Vector z = new Vector();
        Vector r = new Vector();
        Vector g = new Vector();
        Vector b = new Vector();

        z.add(new Double(0));
        z.add(new Double(1.8));
        z.add(new Double(3.6));
        z.add(new Double(5.4));
        z.add(new Double(7.2));


        //z.add(new Double(5));
        //z.add(new Double(100));


        r.add(new Double(0));
        r.add(new Double(.2));
        r.add(new Double(1));
        r.add(new Double(.2));
        r.add(new Double(0));

        g.add(new Double(1));
        g.add(new Double(.75));
        g.add(new Double(.5));
        g.add(new Double(.25));
        g.add(new Double(0));

        b.add(new Double(0));
        b.add(new Double(0.25));
        b.add(new Double(0.50));
        b.add(new Double(0.75));
        b.add(new Double(1.0));

        SurfaceColor sc = new SurfaceColor(currentGrid.getName(),z,r,g,b);

        GridDisplay gridDisplay = new GridDisplay(currentGrid.getName());
        //gridDisplay.drawGrid(currentGrid,sc);
        currentGrid.draw(gridDisplay,sc);
        addToDesktop(gridDisplay);

        System.out.println("sc.getLegendWidth(),sc.getLegendHeight() : " + sc.getLegendWidth() + ", "
                            + sc.getLegendHeight());

        ImageDisplay legendFrame = new ImageDisplay(currentGrid.getName()+
                                        ":Legend",sc.getLegendWidth(),
                                        sc.getLegendHeight());

        addToDesktop(legendFrame);
        sc.drawLegend(legendFrame);

    } //private void drawGrid()






    public void getNewGrid() {

        File filePath = null;

        if(currentFileName != null) {

            File currentFile = new File(currentFileName);
            filePath = currentFile.getParentFile();

        }//if(currentFileName != null)

        File [] aFileList = FileNameDialog.getInputFileNames("Pick new Grid...",filePath,null);

        if(aFileList != null) {

            for(int i=0;i<aFileList.length;i++) {

                File aFile = aFileList[i];

                if ((aFile != null) && (aFile.exists())) {

                    addToGrids(aFile);

                } //if ((aFile != null) && (aFile.exists()))


                else
                    System.out.println("GridManager.getNewGrid(), file is null");


/**
                if ((aFile != null) && (aFile.exists())) {
                    if (gridsType == INSTANT) {
                        Grid aGrid = (Grid) Grid.readGridObject(aFile);
                        if(aGrid != null)
                            addToGrids(aGrid);
                    } //if (gridsType == INSTANT)

                    else if (gridsType == SUMMARY) {
                        Grid2 aGrid = (Grid2) Grid2.readGrid2Object(aFile);
                        if(aGrid != null)
                            addToGrids(aGrid);
                    } //if (gridsType == SUMMARY)
            
                    else if (gridsType == HISTORY) {
                        LCGrid2 aGrid = (LCGrid2) LCGrid2.readLCGrid2Object(aFile);
                        if(aGrid != null)
                            addToGrids(aGrid);
                    } //if (gridsType == HISTORY)

                } //if ((aFile != null) && (aFile.exists()))


                else
                    System.out.println("GridManager.getNewGrid(), file is null");
**/

            } //for(int i=0;i<aFileList.length;i++)

        } //if(aFileList != null)

    } //public void getNewGrid()




    private void addToDesktop(DisplayFrame panel) {

        if(panel == null)
            System.out.println("GridViewControl.addToDesktop(), panel is null");

        firePropertyChange(IDSSAppConstants.addToModelView,null,panel);

    }//private void addToDesktop(DisplayFrame panel)






    //public void addToGrids(GenericGrid grid) {
    public void addToGrids(File aFile) {


        if(!gridsListVector.contains(aFile)) {

            gridsListVector.add(aFile);

            GeneralTableModel tm = (GeneralTableModel) gridsTable.getModel();
            Vector oneRow = new Vector();
            oneRow.add(aFile.toString());
            tm.addRow(oneRow);
            gridsTable.setModel(tm);

            if(gridsListVector.size()>0)
                runButton.setEnabled(true);
            else
                runButton.setEnabled(false);

        } //if(!gridsListVector.contains(aFile))


/**
        if(!gridsListVector.containsKey(grid.getName())) {

            gridsListVector.put(grid.getFileName(),grid);

            GeneralTableModel tm = (GeneralTableModel) gridsTable.getModel();

            Vector rowVector = grid.getGridVector();

            tm.addRow(rowVector);
            gridsTable.setModel(tm);

        } //if(!gridsListVector.containsKey(grid.getFileName()))

        if(gridsListVector.size()>0)
            runButton.setEnabled(true);
        else
            runButton.setEnabled(false);
**/

    } //public void addToDataSet(File aFile)






    private void removeFromGrids() {

        drawButton.setEnabled(false);
        disposeButton.setEnabled(false);

        File currentFile = new File(currentFileName);
        gridsListVector.remove(currentFile);

        GeneralTableModel tm = (GeneralTableModel) gridsTable.getModel();

        tm.removeRow(currentRow);
        gridsTable.setModel(tm);
        if(gridsListVector.size()>0)
            runButton.setEnabled(true);
        else
            runButton.setEnabled(false);


    } //private void removeFromGrids()








    private void describeGrid(Grid aGrid) {

        DocumentDisplay aDocDisplay =
            new DocumentDisplay ("Describing :" + aGrid.getName(),aGrid.showdescription(),"text/HTML");

        addToDesktop(aDocDisplay);

    } //private void describeGrid(Grid aGrid)




    public void propertyChange(PropertyChangeEvent evt) {


        if(evt.getPropertyName().equals(IDSSAppConstants.addToModelView)) {

            firePropertyChange(evt.getPropertyName(),evt.getOldValue(),evt.getNewValue());

        } //if(evt.getPropertyName().equals(IDSSAppConstants.addToModelView))


        if(evt.getPropertyName().equals(IDSSAppConstants.removeFromModelView)) {

            firePropertyChange(evt.getPropertyName(),evt.getOldValue(),evt.getNewValue());

        } //if(evt.getPropertyName().equals(IDSSAppConstants.removeFromModelView))


    } //public void propertyChange(PropertyChangeEvent evt)



} //public class GridViewControl extends JFrame implements ActionListener
