package iDSS.sm;

import java.util.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.awt.image.BufferedImage;
import java.beans.*;
import java.sql.Timestamp;

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




public class ExponentialSurvivalModel implements SurvivalModel, Serializable, ActionListener {


    private double rateOfDescent;
    private double criticalFloodingDepth;
    private long criticalTimeInMillis;

    private String modelName;
    private PropertyChangeSupport pcs;
    private Vector textFieldsVector;

    private DisplayFrame internalFrame;



    public ExponentialSurvivalModel() {

        modelName = "Exponential Model";

        criticalTimeInMillis = 0;

        rateOfDescent = 0;
        criticalFloodingDepth = 0;

        pcs = new PropertyChangeSupport(this);

    } //public ExponentialSurvivalModel()





    public ExponentialSurvivalModel(long criticalTime,double rate,double critDepth) {

        modelName = "Exponential Model";

        if (criticalTime > 0)
            criticalTimeInMillis = criticalTime;
        else
            criticalTimeInMillis = 0;

        if (rate > 0)
            rateOfDescent = rate;
        else
            rateOfDescent = 0;

        if(critDepth >= 0)
            criticalFloodingDepth = critDepth;
        else
            criticalFloodingDepth = 0;

        pcs = new PropertyChangeSupport(this);

    } //public ExponentialSurvivalModel(....)






    public void addPropertyChangeListener(PropertyChangeListener l) {

        pcs.addPropertyChangeListener(l);

    } //public void addPropertyChangeListener(PropertyChangeListener l)





    public void removePropertyChangeListener(PropertyChangeListener l) {

        pcs.removePropertyChangeListener(l);

    } //public void removePropertyChangeListener(PropertyChangeListener l)








    public String getName() {

        return modelName;

    } //public String getName()







    public void setCriticalTime(long criticalTime) {

        criticalTimeInMillis = criticalTime;

    } //public void setCriticalTime(long criticalTime)







    public long getCriticalTime() {

        return criticalTimeInMillis;

    } //public long getCriticalTime()






    public void setRateOfDescent(double descentRate) {

        rateOfDescent = descentRate;

    } //public void setRateOfDescent(double descentRate)








    public double getRateOfDescent() {

        return rateOfDescent;

    } //public double getRateOfDescent()










    public void setCriticalFloodingDepth(double depth) {

        criticalFloodingDepth = depth;

    } //public void setCriticalFloodingDepth(double depth)










    public double getCriticalFloodingDepth(Timestamp t) {

        return criticalFloodingDepth;

    } //public double getCriticalFloodingDepth(Timestamp t)








    public double getProbability(long duration,double depth,Timestamp t) {

        double p = Math.exp((double)(criticalTimeInMillis-duration)*rateOfDescent);
        p = Math.min(1,p);

        return p;

    } //public double getProbability(double duration,Timestamp t)








    public DisplayFrame showDetails(boolean editable) {


        internalFrame = new DisplayFrame(modelName,false,true,false,true,null);

        DrawingPanel2 picturePanel = new DrawingPanel2(300,150);
        ExponentialSurvivalModel.drawModel(picturePanel);

        JLabel criticalTimeLabel = new JLabel("Critical flooding length (days):");
        JLabel rateOfDescentLabel = new JLabel("Rate of descent of probability:");
        JLabel criticalFloodingDepthLabel = new JLabel("Cirtical flood depth (depth units):");

        JTextField criticalTimeTextField = new JTextField(String.valueOf((double)criticalTimeInMillis/(1000*60*60*24)),10);
        JTextField rateOfDescentTextField = new JTextField(String.valueOf(rateOfDescent),10);
        JTextField criticalFloodingDepthTextField = new JTextField(String.valueOf(criticalFloodingDepth),10);

        criticalTimeTextField.setEditable(editable);
        rateOfDescentTextField.setEditable(editable);
        criticalFloodingDepthTextField.setEditable(editable);

        textFieldsVector = new Vector();
        textFieldsVector.add(criticalTimeTextField);
        textFieldsVector.add(rateOfDescentTextField);
        textFieldsVector.add(criticalFloodingDepthTextField);

        JButton acceptButton = new JButton(IDSSAppConstants.acceptButtonText);
        acceptButton.setEnabled(editable);
        acceptButton.setActionCommand(IDSSAppConstants.acceptButtonCommand);
        acceptButton.addActionListener(this);

        JPanel textPanel = new JPanel();
        textPanel.setLayout(new GridLayout(3,2));
        textPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
        textPanel.add(criticalTimeLabel);
        textPanel.add(criticalTimeTextField);
        textPanel.add(rateOfDescentLabel);
        textPanel.add(rateOfDescentTextField);
        textPanel.add(criticalFloodingDepthLabel);
        textPanel.add(criticalFloodingDepthTextField);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new BoxLayout(buttonPanel,BoxLayout.X_AXIS));
        buttonPanel.add(Box.createHorizontalGlue());
        buttonPanel.add(acceptButton);


        internalFrame.getContentPane().setLayout(new BoxLayout(internalFrame.getContentPane(),BoxLayout.Y_AXIS));
        internalFrame.getContentPane().add(picturePanel);
        internalFrame.getContentPane().add(textPanel);
        internalFrame.getContentPane().add(buttonPanel);
        internalFrame.pack();
        internalFrame.setVisible(true);

        return internalFrame;

    } //public DisplayFrame showDetails(boolean editable)








    public static void drawModel(DrawingPanel2 picturePanel) {


        BufferedImage bi = picturePanel.getCanvas();
        Graphics g = bi.getGraphics();

        int sizeX = picturePanel.getCanvasX();
        int sizeY = picturePanel.getCanvasY();

        g.setColor(Color.lightGray);
        g.fillRect(0,0,sizeX,sizeY);

        int margin = 35;
        int drawAreaX = sizeX-2*margin;
        int drawAreaY = sizeY-2*margin;
        int tic = 3;

        g.setColor(Color.black);
        g.drawLine(margin,margin,margin,sizeY-margin);
        g.drawLine(margin,sizeY-margin,sizeX-margin,sizeY-margin);

        g.drawLine(margin,margin+drawAreaY/3,margin+drawAreaX/3,margin+drawAreaY/3);
        g.drawArc(margin+drawAreaX/3,margin-drawAreaY/3,drawAreaX*4/3,drawAreaY*4/3,180,90);

        g.drawLine(margin+drawAreaX,margin+drawAreaY,margin+drawAreaX,margin+drawAreaY-tic);
        g.drawLine(margin+drawAreaX/3,margin+drawAreaY,margin+drawAreaX/3,margin+drawAreaY-tic);

        g.drawString("0",margin-2,margin+drawAreaY+15);
        g.drawString("Critical time",margin+drawAreaX/3-10,margin+drawAreaY+15);
        g.drawString("365",margin+drawAreaX-10,margin+drawAreaY+15);
        g.drawString("0",margin-15,margin+drawAreaY+2);
        g.drawString("1",margin-15,margin+drawAreaY/3+2);
        g.drawString("Days of the year",margin,margin+drawAreaY+30);
        g.drawString("Probability of survival",margin,margin-5);

        //picturePanel.refreshCanvas(bi);

    } //public void drawModel(DrawingPanel2 picturePanel)








    public void actionPerformed(ActionEvent ae) {

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

            JTextField tf;

            tf = (JTextField)textFieldsVector.elementAt(0);
            double critTimeDouble = Double.parseDouble(tf.getText())*24*60*60*1000;
            //long criticalTime = Long.parseLong(tf.getText());
            //criticalTime = criticalTime*24*60*60*1000;
            long criticalTime = Math.round(critTimeDouble);

            tf = (JTextField)textFieldsVector.elementAt(1);
            double descentRate = Double.parseDouble(tf.getText());

            tf = (JTextField)textFieldsVector.elementAt(2);
            double critFD = Double.parseDouble(tf.getText());

            setCriticalTime(criticalTime);
            setRateOfDescent(descentRate);
            setCriticalFloodingDepth(critFD);

            pcs.firePropertyChange(IDSSAppConstants.setSurvivalModel,null,getCopy());
            pcs.firePropertyChange(IDSSAppConstants.removeFromModelView,null,internalFrame);

            //internalFrame.setClosed(true);

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

    } //public void actionPerformed(ActionEvent ae)





    public SurvivalModel getCopy() {

        Timestamp t = null;
        SurvivalModel aModel = new ExponentialSurvivalModel(
            getCriticalTime(),
            getRateOfDescent(),
            getCriticalFloodingDepth(t)
        );

        return aModel;

    } //public SurvivalModel getCopy()





    public Hashtable getParameters() {

        Hashtable h = new Hashtable();

        h.put("criticalTimeInMillis",new Long(criticalTimeInMillis));
        h.put("rateOfDescent",new Double(rateOfDescent));
        h.put("criticalFloodingDepth",new Double(criticalFloodingDepth));

        return h;

    } //public Hashtable getParameters()






    public void setParameters(Hashtable h) {

        criticalTimeInMillis = StringHandler.stringToLong((String)h.get("criticalTimeInMillis"));
        rateOfDescent = StringHandler.stringToDouble((String)h.get("rateOfDescent"));
        criticalFloodingDepth = StringHandler.stringToDouble((String)h.get("criticalFloodingDepth"));

    } //public void setParameters(Hashtable h)



} //public class ExponentialSurvivalModel
