package iDSS.sim;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.table.AbstractTableModel;
import java.sql.Timestamp;
import java.util.*;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;
import java.awt.image.*;
import javax.swing.event.*;
import java.io.*;
import java.beans.*;




import iDSS.*;
import iDSS.utils.*;
import iDSS.disp.*;
import iDSS.grids.*;
import iDSS.tidalData.*;
import iDSS.sm.*;
import iDSS.gView.*;
import iDSS.beans2.*;



public class Simulation extends DisplayFrame implements ActionListener,Runnable,PropertyChangeListener {



    private JTextField nameTextField;
    private JTextField simulateUntilTextField;
    private JTextField timestepTextField;
    private JTextField resultsTimestepTextField;

    private JComboBox simulateUntilCombo;
    private JComboBox timestepUnitsCombo;
    private JComboBox resultsTimestepUnitCombo;

    private JButton seawallButton;
    private JButton startSimulationButton;

    private JLabel nameLabel;
    private JLabel simulateUntilLabel;
    private JLabel timestepLabel,resultsTimestepLabel;

    private Thread simulationThread;


    private JLabel  viewFloodGridLabel,
                    saveFloodGridLabel,
                    viewDDGraphLabel,
                    saveDDGraphLabel;

    private JLabel  currentYearLabel,
                    currentMonthLabel,
                    currentDayLabel,
                    percentProgressLabel;

    private JTextField currentYearTextField,
                        currentMonthTextField,
                        currentDayTextField,
                        percentProgressTextField;

    private JTextField coordsTextField;

    private JCheckBox viewFloodGridCB,saveFloodGridCB,viewDDGraphCB,saveDDGraphCB;

    private JPanel namePanel,simulateUntilPanel,timestepPanel,statusTimestepPanel,
                    statusPanel,forEachTimestepPanel,startButtonpanel;

    private JPanel coordsPanel;

    private String simulationName,saveLocationName;


    private JButton viewSummaryGridsButton,viewFloodGridsButton;

    private SimulationJBean simulationJBean;






    public Simulation (Grid dem,LCGrid2 lc,Hashtable tm,int isostatic,ClientDataSet slr) {

        super(IDSSAppConstants.simTitle,false,false, false, true, null);

        simulationJBean = new SimulationJBean();
        simulationJBean.addPropertyChangeListener(this);

        simulationJBean.setDem(dem);
        simulationJBean.setLcGrid2(lc);
        simulationJBean.setTidalModelHashtable(tm);
        simulationJBean.setIsostaticMovement(isostatic);
        simulationJBean.setSlrDataSet(slr);

    } //public Simulation (Grid dem,LCGrid2 lc,Hashtable tm,int isostatic,ClientDataSet slr)
    


    public void run() {


        //NamePanel
        nameLabel = new JLabel("Name of simulation:");
        nameTextField = new JTextField(20);
        namePanel = new JPanel();
        namePanel.setLayout(new FlowLayout(FlowLayout.LEFT));
        namePanel.add(nameLabel);
        namePanel.add(nameTextField);

        //NamePanel - end 


        //simulateUntilPanel

        simulateUntilLabel = new JLabel("Simulate until: ");

        simulateUntilCombo = new JComboBox(simulationJBean.getSimUntilYears());

        simulateUntilCombo.setPreferredSize(new Dimension(5,5));
        seawallButton = new JButton("Add/Edit Seawall");

        simulateUntilPanel = new JPanel();
        simulateUntilPanel.setLayout(new BoxLayout(simulateUntilPanel,BoxLayout.X_AXIS));
        simulateUntilPanel.add(simulateUntilLabel);
        simulateUntilPanel.add(simulateUntilCombo);
        simulateUntilPanel.add(Box.createHorizontalGlue());
        simulateUntilPanel.add(seawallButton);

        //simulateUntilPanel - end



        //timestepPanel

        timestepLabel = new JLabel("Time step: ");
        timestepTextField = new JTextField(3);
        String [] timestepUnits = {"Hours","Minutes"};
        timestepUnitsCombo = new JComboBox(timestepUnits);

        resultsTimestepLabel = new JLabel("Results every ");
        resultsTimestepTextField = new JTextField(3);
        String [] resultsTimestepUnits = {"Years"};
        resultsTimestepUnitCombo = new JComboBox(resultsTimestepUnits);

        timestepPanel = new JPanel();
        timestepPanel.setLayout(new BoxLayout(timestepPanel,BoxLayout.X_AXIS));
        timestepPanel.add(timestepLabel);
        timestepPanel.add(timestepTextField);
        timestepPanel.add(timestepUnitsCombo);
        timestepPanel.add(Box.createHorizontalStrut(10));
        timestepPanel.add(resultsTimestepLabel);
        timestepPanel.add(resultsTimestepTextField);
        timestepPanel.add(resultsTimestepUnitCombo);

        //timestepPanel - end


        //statusPanel

        currentYearLabel = new JLabel("Current Year");
        currentMonthLabel = new JLabel("Current Month");
        currentDayLabel = new JLabel("Current Day");
        percentProgressLabel = new JLabel("% Progress");

        currentYearTextField = new JTextField();
        currentMonthTextField = new JTextField();
        currentDayTextField = new JTextField();
        percentProgressTextField = new JTextField();

        currentYearTextField.setEditable(false);
        currentMonthTextField.setEditable(false);
        currentDayTextField.setEditable(false);
        percentProgressTextField.setEditable(false);

        statusPanel = new JPanel();
        statusPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),"Simulation status"));
        statusPanel.setLayout(new GridLayout(4,2));

        statusPanel.add(currentYearLabel);
        statusPanel.add(currentYearTextField);
        statusPanel.add(currentMonthLabel);
        statusPanel.add(currentMonthTextField);
        statusPanel.add(currentDayLabel);
        statusPanel.add(currentDayTextField);
        statusPanel.add(percentProgressLabel);
        statusPanel.add(percentProgressTextField);

        //statusPanel - end

        //forEachTimestepPanel

        viewFloodGridLabel = new JLabel("View flood grid:");
        saveFloodGridLabel = new JLabel("Save flood grid:");
        viewDDGraphLabel = new JLabel("View depth-duration graph:");
        saveDDGraphLabel = new JLabel("Save depth-duration graph:");

        viewFloodGridCB = new JCheckBox();
        saveFloodGridCB = new JCheckBox();
        viewDDGraphCB = new JCheckBox();
        saveDDGraphCB = new JCheckBox();

        JPanel viewFloodGridPanel = new JPanel();
        JPanel saveFloodGridPanel = new JPanel();
        JPanel viewDDGraphPanel = new JPanel();
        JPanel saveDDGraphPanel = new JPanel();

        viewFloodGridPanel.setLayout(new BoxLayout(viewFloodGridPanel,BoxLayout.X_AXIS));
        saveFloodGridPanel.setLayout(new BoxLayout(saveFloodGridPanel,BoxLayout.X_AXIS));
        viewDDGraphPanel.setLayout(new BoxLayout(viewDDGraphPanel,BoxLayout.X_AXIS));
        saveDDGraphPanel.setLayout(new BoxLayout(saveDDGraphPanel,BoxLayout.X_AXIS));


        viewFloodGridPanel.add(viewFloodGridLabel);
        viewFloodGridPanel.add(Box.createHorizontalGlue());
        viewFloodGridPanel.add(viewFloodGridCB);

        saveFloodGridPanel.add(saveFloodGridLabel);
        saveFloodGridPanel.add(Box.createHorizontalGlue());
        saveFloodGridPanel.add(saveFloodGridCB);

        viewDDGraphPanel.add(viewDDGraphLabel);
        viewDDGraphPanel.add(Box.createHorizontalGlue());
        viewDDGraphPanel.add(viewDDGraphCB);

        saveDDGraphPanel.add(saveDDGraphLabel);
        saveDDGraphPanel.add(Box.createHorizontalGlue());
        saveDDGraphPanel.add(saveDDGraphCB);

        forEachTimestepPanel = new JPanel();
        forEachTimestepPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),"For each result"));
        forEachTimestepPanel.setLayout(new GridLayout(4,1));

        forEachTimestepPanel.add(viewFloodGridPanel);
        forEachTimestepPanel.add(saveFloodGridPanel);
        forEachTimestepPanel.add(viewDDGraphPanel);
        forEachTimestepPanel.add(saveDDGraphPanel);

        //forEachTimestepPanel - end


        //statusTimestepPanel

        statusTimestepPanel = new JPanel();
        statusTimestepPanel.setLayout(new BoxLayout(statusTimestepPanel,BoxLayout.X_AXIS));

        statusTimestepPanel.add(statusPanel);
        statusTimestepPanel.add(Box.createHorizontalGlue());
        statusTimestepPanel.add(forEachTimestepPanel);

        //statusTimestepPanel - end

        //coordsPanel -- start

        coordsPanel = new JPanel();
        coordsPanel.setBorder(BorderFactory.createTitledBorder(
                    BorderFactory.createEtchedBorder(),"Flood start point(s), x,y,x,y..."));
        coordsTextField = new JTextField(40);
        coordsPanel.add(coordsTextField);

        //coordsPanel -- end


        //startButtonpanel

        viewSummaryGridsButton = new JButton(IDSSAppConstants.viewSummaryGridsButtonText);
        viewFloodGridsButton = new JButton(IDSSAppConstants.viewFloodGridsButtonText);
        startSimulationButton = new JButton(IDSSAppConstants.startSimulationButtonText);

        viewSummaryGridsButton.setActionCommand(IDSSAppConstants.viewSummaryGridsButtonCommand);
        viewFloodGridsButton.setActionCommand(IDSSAppConstants.viewFloodGridsButtonCommand);
        startSimulationButton.setActionCommand(IDSSAppConstants.startSimulationButtonCommand);

        viewSummaryGridsButton.addActionListener(this);
        viewFloodGridsButton.addActionListener(this);
        startSimulationButton.addActionListener(this);

        viewSummaryGridsButton.setEnabled(true);
        viewFloodGridsButton.setEnabled(true);
        startSimulationButton.setEnabled(true);

        startButtonpanel = new JPanel();
        startButtonpanel.setLayout(new BoxLayout(startButtonpanel,BoxLayout.X_AXIS));

        startButtonpanel.add(Box.createHorizontalGlue());
        startButtonpanel.add(viewSummaryGridsButton);
        startButtonpanel.add(viewFloodGridsButton);
        startButtonpanel.add(startSimulationButton);

        //startButtonpanel - end

        getContentPane().setLayout(new BoxLayout(getContentPane(),BoxLayout.Y_AXIS));

        getContentPane().add(namePanel);
        getContentPane().add(simulateUntilPanel);
        getContentPane().add(timestepPanel);
        getContentPane().add(statusTimestepPanel);
        getContentPane().add(coordsPanel);
        getContentPane().add(startButtonpanel);

        pack();
        setVisible(true);

    } //public void run()





    public void actionPerformed(ActionEvent ae) {

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

            if(validateInput()) {

                File saveLocationDir = getSaveLoc("Choose directory","Choose  location for saving results");
                simulationJBean.setSaveLocationDir(saveLocationDir);

                if (simulationJBean.validateInput()) {

                    if(saveLocationDir != null) {

                        SimulationRun simRun = new SimulationRun();
                        simRun.setSimulationData(simulationJBean);

                        simRun.removePropertyChangeListener(this);
                        simRun.addPropertyChangeListener(this);

                        simulationThread = new Thread(simRun);
                        simulationThread.start();


                    } //if(saveLocationFile != null)

                } //if (simulationJBean.validateInput())

            } //if(validateInput())

        }//if (ae.getSource() == startSimulationButton)


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

            GridViewControl gvc = new GridViewControl(GridViewControl.SUMMARY,"Summary Grids");
            gvc.removePropertyChangeListener(this);
            gvc.addPropertyChangeListener(this);
            firePropertyChange(IDSSAppConstants.addToModelView,null,gvc);
            gvc.removePropertyChangeListener(this);
            gvc.addPropertyChangeListener(this);

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



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

            GridViewControl gvc = new GridViewControl(GridViewControl.INSTANT,"Flood Grids");
            gvc.removePropertyChangeListener(this);
            gvc.addPropertyChangeListener(this);
            firePropertyChange(IDSSAppConstants.addToModelView,null,gvc);
            gvc.removePropertyChangeListener(this);
            gvc.addPropertyChangeListener(this);


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




    } //public void actionPerformed(ActionEvent ae)









    private boolean validateInput() {

        System.out.println("Validating input for simulation");
        boolean validInput = true;

        if (nameTextField.getText().length() < 1) {
            JOptionPane.showMessageDialog(null,"Missing simulation name","Simulation name error",JOptionPane.ERROR_MESSAGE);
            validInput = false;
            return validInput;
        }

        simulationJBean.setSimulationName(nameTextField.getText());

        //get timestep
        String timestepString = timestepTextField.getText();

        try {
            int timestepMinutes = Integer.parseInt(timestepString);

            if (((String)timestepUnitsCombo.getSelectedItem()).equals("Hours"))
                    timestepMinutes = timestepMinutes*60;

            simulationJBean.setTimestepMinutes(timestepMinutes);
            System.out.println("timestepMinutes = " + timestepMinutes);

        }

        catch (NumberFormatException nfe) {

            System.out.println(nfe);
            JOptionPane.showMessageDialog(null,"Time step must be a positive non-zero integer","Time step error",JOptionPane.ERROR_MESSAGE);
            validInput = false;
            return validInput;

        } //catch (NumberFormatException nfe)


        

        //get resultsTimestepYears
        String resultStep = resultsTimestepTextField.getText();
        try {
            int resultsTimestepYears = Integer.parseInt(resultStep);
            simulationJBean.setResultsTimestepYears(resultsTimestepYears);
            System.out.println("resultsTimestepYears = " + resultsTimestepYears);
        }

        catch (NumberFormatException nfe) {

            System.out.println(nfe);
            JOptionPane.showMessageDialog(null,"Results time step must be a positive non-zero integer","Results time step error",JOptionPane.ERROR_MESSAGE);
            validInput = false;
            return validInput;

        } //catch (NumberFormatException nfe)


        if (coordsTextField.getText().length() < 1) {
            JOptionPane.showMessageDialog(null,"Missing flood start points","Flood start error",JOptionPane.ERROR_MESSAGE);
            validInput = false;
            return validInput;
        }


        simulationJBean.setFloodStartVector(coordsTextField.getText());

        simulationJBean.setViewFG(viewFloodGridCB.isSelected());
        simulationJBean.setSaveFG(saveFloodGridCB.isSelected());
        simulationJBean.setViewDD(viewDDGraphCB.isSelected());
        simulationJBean.setSaveDD(saveDDGraphCB.isSelected());

        simulationJBean.setSimulateUntil(((Integer)simulateUntilCombo.getSelectedItem()).intValue());


/**

        simulateUntil = ((Integer)simulateUntilCombo.getSelectedItem()).intValue();

        System.out.println("Simulate until       : " + simulateUntil);
        System.out.println("Simulation time step : " + timestepMinutes);
        System.out.println("Results time step    : " + resultsTimestepYears);
        System.out.println("View Flood Grid      : " + viewFG);
        System.out.println("Save Flood Grid      : " + saveFG);
        System.out.println("View Depth Duration  : " + viewDD);
        System.out.println("Save Depth Duration  : " + saveDD);
**/
        return validInput;

    } //private boolean validateInput()







    private File getSaveLoc(String approveButtonText,String dialogTitle) {


        File outDir = FileNameDialog.getOutputDirectory(approveButtonText,dialogTitle,null,null);
        return outDir;

    } //public String getSaveLoc()






    public void setStatus(Timestamp t) {


        Calendar cal = Calendar.getInstance();
        cal.setTime(t);
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        int date = cal.get(Calendar.DATE);

        currentYearTextField.setText(String.valueOf(year));
        currentMonthTextField.setText(String.valueOf(month+1));
        currentDayTextField.setText(String.valueOf(date));

        //System.out.println("In Simulation.setStatus(): " + t.toString());

        //percentProgressTextField;


    } //public void setStatus(Timestamp t)





    public void propertyChange(PropertyChangeEvent evt) {



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

            Timestamp t = (Timestamp)evt.getNewValue();
            setStatus(t);
            simulationJBean.setStatus(t);

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


        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))


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

            viewSummaryGridsButton.setEnabled(true);
            viewFloodGridsButton.setEnabled(true);

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


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

            MessageHandler.showMessage((Vector)evt.getNewValue());

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



    } //public void propertyChange(PropertyChangeEvent evt)




    public String toString() {

        return IDSSAppConstants.simTitle + " window";

    } //public String toString()



} //public class simulationPanel

