package iDSS.grids;

import java.io.*;
import java.util.*;
import java.sql.Timestamp;


import iDSS.sm.*;
import iDSS.utils.*;


public class GridCell implements Serializable {

    private long totalFloodingTime; //in millisecs
    private long totalDryTime; //millisecs
    private double highestDepthOfFlooding;
    private long longestFloodingTime; //millisecs
    private long longestDryTime; //millisecs
    private long totalCriticalFloodingTime; //millisecs
    private long longestCriticalFloodingTime; //millisecs
    private long currentFloodingTime;
    private long currentDryTime;
    private long currentCriticalFloodingTime;
    private double probabilityOfSurvival,minimumProbabilityOfSurvival;

    private boolean flooded;
    private boolean criticallyFlooded,criticalFloodingEnds;
    private boolean dry;






    public GridCell() {

        totalFloodingTime = 0;
        totalDryTime = 0;
        highestDepthOfFlooding = 0;
        longestFloodingTime = 0;
        longestDryTime = 0;
        totalCriticalFloodingTime = 0;
        longestCriticalFloodingTime = 0;
        currentFloodingTime = 0;
        currentDryTime = 0;
        currentCriticalFloodingTime = 0;
        probabilityOfSurvival = 1;
        minimumProbabilityOfSurvival = 1;

        flooded = false;
        criticallyFlooded = false;
        dry = false;
        criticalFloodingEnds = false;

    } //public GridCell()




    public static Vector getParametersVector() {

        Vector parameters = new Vector();

        parameters.add(IDSSAppConstants.totalFloodingTime);
        parameters.add(IDSSAppConstants.totalDryTime);
        parameters.add(IDSSAppConstants.highestDepthOfFlooding);
        parameters.add(IDSSAppConstants.longestFloodingTime);
        parameters.add(IDSSAppConstants.longestDryTime);
        parameters.add(IDSSAppConstants.totalCriticalFloodingTime);
        parameters.add(IDSSAppConstants.longestCriticalFloodingTime);
        parameters.add(IDSSAppConstants.minimumProbabilityOfSurvival);

        return parameters;

    } //public Vector getParametersVector()










    public String getValue(String s) {

        String aString = null;
        double value = 0;
        if (s.equals(IDSSAppConstants.totalFloodingTime))
            value = (double)totalFloodingTime;

        else if (s.equals(IDSSAppConstants.totalDryTime))
            value = (double)totalDryTime;

        else if (s.equals(IDSSAppConstants.highestDepthOfFlooding))
            value = highestDepthOfFlooding;

        else if (s.equals(IDSSAppConstants.longestFloodingTime))
            value = (double)longestFloodingTime;

        else if (s.equals(IDSSAppConstants.longestDryTime))
            value = (double)longestDryTime;

        else if (s.equals(IDSSAppConstants.totalCriticalFloodingTime))
            value = (double)totalCriticalFloodingTime;

        else if (s.equals(IDSSAppConstants.longestCriticalFloodingTime))
            value = (double)longestCriticalFloodingTime;

        else if (s.equals(IDSSAppConstants.minimumProbabilityOfSurvival))
            value = minimumProbabilityOfSurvival;


        aString = String.valueOf(value);
        //System.out.println("GridCell.getValue(), s = " + s + " val = " + value + " aString = " + aString);
        return aString;

    } //public String getValue(String s) 









    public void addToTotalFloodingTime(long t) {

        totalFloodingTime = totalFloodingTime+t;

    }



    public long getTotalFloodingTime() {

        return totalFloodingTime;

    }




    public void addToCurrentFloodingTime(long t) {


        if(dry) {
            longestDryTime = Math.max(currentDryTime,longestDryTime);
            currentDryTime = 0;
            dry = false;
        }

        else if(criticallyFlooded) {

            longestCriticalFloodingTime = Math.max(currentCriticalFloodingTime,longestCriticalFloodingTime);
            criticallyFlooded = false;
            criticalFloodingEnds = true;
       }


        flooded = true;
        currentFloodingTime = currentFloodingTime+t;

    } //public void addToCurrentFloodingTime(long t)







    public void addToTotalDryTime(long t) {

        totalDryTime = totalDryTime+t;

    }




    public long getTotalDryTime() {

        return totalDryTime;

    }




    public void addToCurrentDryTime(long t) {


        if(criticallyFlooded) {

            longestCriticalFloodingTime = Math.max(currentCriticalFloodingTime,longestCriticalFloodingTime);
            criticallyFlooded = false;
            criticalFloodingEnds = true;

            longestFloodingTime = Math.max(currentFloodingTime,longestFloodingTime);
            currentFloodingTime = 0;
            flooded = false;

        } //if(criticallyFlooded)

        else if(flooded) {

            longestFloodingTime = Math.max(currentFloodingTime,longestFloodingTime);
            currentFloodingTime = 0;
            flooded = false;

        } //if(flooded)

        dry = true;
        currentDryTime = currentDryTime+t;

    } //public void addToCurrentDryTime(long t)




    public long getLongestDryTime() {

        return longestDryTime;

    } //public long getLongestDryTime()






    public void setHighestDepthOfFlooding(double d) {

        if(highestDepthOfFlooding < d)
            highestDepthOfFlooding = d;

    }


    public double getHighestDepthOfFlooding() {

        return highestDepthOfFlooding;

    }





    public long getLongestFloodingTime() {

        return longestFloodingTime;

    }





    public void addToTotalCriticalFloodingTime(long t) {

        totalCriticalFloodingTime = totalCriticalFloodingTime+t;
        totalFloodingTime = totalFloodingTime+t;

    }



    public void addToCurrentCriticalFloodingTime(long t) {


        if (dry) {
            longestDryTime = Math.max(currentDryTime,longestDryTime);
            currentDryTime = 0;
            dry = false;
        }

        criticallyFlooded = true;
        currentCriticalFloodingTime = currentCriticalFloodingTime+t;

        flooded = true;
        currentFloodingTime = currentFloodingTime+t;


    } //public void addToCurrentCriticalFloodingTime(long t)








    public long getTotalCriticalFloodingTime() {

        return totalCriticalFloodingTime;

    }






    public long getLongestCriticalFloodingTime() {

        return longestCriticalFloodingTime;

    }










    public void buildUP(double floodDepth,long simTS,Timestamp currentTime,SurvivalModel sm) {

        double criticalFD = sm.getCriticalFloodingDepth(currentTime);

        if(floodDepth > criticalFD) {

            addToTotalCriticalFloodingTime(simTS);
            addToCurrentCriticalFloodingTime(simTS);
            setHighestDepthOfFlooding(floodDepth);

        } //if(floodDepth > criticalFD)

        else if(floodDepth > 0) {

            addToTotalFloodingTime(simTS);
            addToCurrentFloodingTime(simTS);
            setHighestDepthOfFlooding(floodDepth);

        } //if(floodDepth > 0)

        else {

            addToTotalDryTime(simTS);
            addToCurrentDryTime(simTS);

        } //else



        if(criticalFloodingEnds) {

            //System.out.println("GridCell.buildUp(), minProb = " + minimumProbabilityOfSurvival);

            criticalFloodingEnds = false;
            probabilityOfSurvival = sm.getProbability(currentCriticalFloodingTime,criticalFD,currentTime);
            minimumProbabilityOfSurvival = Math.min(minimumProbabilityOfSurvival,probabilityOfSurvival);
            currentCriticalFloodingTime = 0;

            //System.out.println("GridCell.buildUp(), minProb = " + minimumProbabilityOfSurvival);
            //System.out.println("GridCell.buildUp(), prob = " + probabilityOfSurvival);

        } //if(criticalFloodingEnds)


    } //public void buildUP(double floodDepth,long simTS)






    public void roundUp(SurvivalModel sm,long simTS,double floodDepth,Timestamp currentTime) {


        if (criticallyFlooded) {

            //System.out.println("GridCell.roundUp(), minProb = " + minimumProbabilityOfSurvival);

            longestCriticalFloodingTime = Math.max(currentCriticalFloodingTime,longestCriticalFloodingTime);

            longestFloodingTime = Math.max(currentFloodingTime,longestFloodingTime);

            probabilityOfSurvival =
                sm.getProbability(currentCriticalFloodingTime,sm.getCriticalFloodingDepth(currentTime),currentTime);

            minimumProbabilityOfSurvival = Math.min(probabilityOfSurvival,minimumProbabilityOfSurvival);

            //System.out.println("GridCell.roundUp(), minProb = " + minimumProbabilityOfSurvival);
            //System.out.println("GridCell.roundUp(), prob = " + probabilityOfSurvival);


            criticalFloodingEnds = false;
            currentCriticalFloodingTime = 0;
            currentFloodingTime = 0;

        }

        else if (flooded) {

            //System.out.println("flooded, currentFloodingTime = " + currentFloodingTime);

            longestFloodingTime = Math.max(currentFloodingTime,longestFloodingTime);
            currentFloodingTime = 0;

        }

        else if (dry) {

            //System.out.println("dry, currentDryTime = " + currentDryTime);

            longestDryTime = Math.max(currentDryTime,longestDryTime);
            currentDryTime = 0;

        }


    } //public void roundUp(SurvivalModel sm,long simTS,double floodDepth,Timestamp currentTime)







    public String getStatus() {

        String status = "";

        if (criticallyFlooded) {

            status = "criticallyFlooded";

        }

        else if (flooded) {

            status = "flooded";

        }

        else if (dry) {

            status = "dry";

        }

        return status;

    } //public String getStatus()



} //public class GridCell


