
/*
 * MarksAutonome.java
 *
 * Created on 06 December 2004, 14:07
 */
import java.io.*;
/**
 * Class to extend CellularAutonome by providing temporal update rules
 *
 * @author mnaylor
 */
public class LomnitzAutonome extends CellularAutonome11 {
    /**
     * Thread to run CellularAutonome model in
     */
    public static MyThread autonomeThread;
    /**
     * Sleep duration during time iteration
     */
    private static int autonomeThreadSleepDuration = (int) 1;  // 1000 / 24 ;
    /**
     * Creates a new instance of MarksAutonome
     *
     */
    public  LomnitzAutonome() {
        autonomeThread = new MyThread( );
        init();
        initStreams();
    }
    /**
     * Main autonome thread
     */
    class MyThread extends Thread {
        
        /**
         * Sets the pleaseWait variable true
         */
        boolean pleaseWait = false;
        // This method is called when the thread runs
        
        /**
         * The autonome main time iteration thread
         */
        public void run() {
            
            while (true) {
                // Do work
                synchronized (this) {
                    while (pleaseWait) {
                        try { wait();} catch (Exception e) {}
                    }
                }
                
                try { autonomeThread.sleep(autonomeThreadSleepDuration); }catch (InterruptedException ie) {}
                incrementTime();
                sendDataToDataStream();
                repaint();
                
            }
        }
    }
    
    /**
     * Rule to propagate ruptures
     *
     */
    public void rupturePropagation() {
        // Set test for loop to false
        newRuptures = false ;
        // Increment cells adjacent to new rupture
        for (int n = 0; n < TotalCellNumber; n++){
            if ( allCells[n].isStressAboveThreshold() ) {
                allCells[n].initiateRupture();
                newRuptures = true;
                numberOfRupturesFromSite[initialRuptureSite[n]]++;
                allCells[n].setCellStressZero();
                propagateStressToNeighboursOf(n);     
            }
        }
    }
    
//    public void rupturePropagation() {
//        // Set test for loop to false
//        newRuptures = false ;
//        // Increment cells adjacent to new rupture
//        for (int n = 0; n < TotalCellNumber; n++){
//            if ( allCells[n].isStressAboveThreshold() ) {
//                allCells[n].initiateRupture();
//                newRuptures = true;
//                numberOfRupturesFromSite[initialRuptureSite[n]]++;
//            }
//        }
//        
//        for (int n = 0; n < TotalCellNumber; n++){
//            if ( allCells[n].isCellStressFlagged() ) {
//                allCells[n].setCellStressZero();
//                propagateStressToNeighboursOf(n);     
//            }
//        }
//    }
    
    /**
     * Applies timesetp update and sets up the first layer of new ruptures
     *
     */
    public void incrementTime() {
        double stressIncrement;
        time++;
//        if(time>runtimeDuration){ pauseAutonome(); saveData(); readyForNextJob();}
        if(totalLoadingStress>4){ pauseAutonome(); saveData(); readyForNextJob();}
        else{
//            System.out.println("Time = " + time + " Total Stress Load = " + totalLoadingStress) ;
            for (int n = 0; n < TotalCellNumber; n++){
                // Reset so cells can only be reset once each timestep
                allCells[n].setCellNotRuptured();
            }
            
            double loadingStressIncrement = getStressIncrement( loadingMechanism );
            double outputStressIncrement = nextOutputLoadingStress-totalLoadingStress;
            if(loadingStressIncrement < outputStressIncrement)
                {stressIncrement = loadingStressIncrement;}
            else{
                stressIncrement = outputStressIncrement; 
                nextOutputLoadingStress += loadingStressOutputIncrement;
                System.out.println("Output time = " + time + " Total Stress Load = " + totalLoadingStress) ;
            }
            
            totalLoadingStress += stressIncrement;
            totalNumberOfRuptures=0;
            
            for (int n = 0; n < TotalCellNumber; n++){
                // Increment stress
                allCells[n].incrementStress(stressIncrement, percentageNoise);
                numberOfRupturesFromSite[n]=0;
                
                // Check to see if cell is above threshold
                if ( allCells[n].isStressAboveThreshold() ) {
                    newRuptures = true;
                    initialRuptureSite[n]=n;
                    totalNumberOfRuptures++;
                    runningRuptureCount++;
                }
                else{ initialRuptureSite[n]=-1; }                     
            }
            
            try { fwRuptureNumber.write(time + " " + totalNumberOfRuptures + " " + totalLoadingStress + "\n"); } catch (IOException e) {}
            
            // If any cells above threshold, propagate the ruptures
            while ( newRuptures ) {
                rupturePropagation();
            }
            
//            countClusterAreas();
//            countClusterAreas2();
        }
    }
    
    /**
     * Set the number of run time iterations before stopping and saving the run.
     * This must be large for uninterupted evolution in the GUI.
     * @param value runtime Duration
     */
    public void setRuntimeDuration(int value){ runtimeDuration = value; }
    
    /**
     * Initiates getting the next batch file entry
     */
    private void readyForNextJob(){ BatchFromStrippedGUI2.runNextBatchEntry(); }
      
    /**
     * Sets the sleep duration for each run. This is small for the best performance,
     * but can be increased to better visual effect
     * @param value autonomeThreadSleepDuration
     */
    public void setAutonomeThreadSleepDuration(int value){ autonomeThreadSleepDuration = value; }
    
    /**
     * Resets time to zero, the autonome parameters and opens the new file streams.
     */
    public void resetAutonome() {time=0; init(); initStreams();}
        
    /**
     * Updates area frequency statistics
     */
    private void countClusterAreas2(){
        for(int n = 0; n < TotalCellNumber; n++){
            if(numberOfRupturesFromSite[n]>0){
                areaFreqHist2[numberOfRupturesFromSite[n]]++;
                areaFreqHistInterval[numberOfRupturesFromSite[n]]++;
                areaFreqHistCum[numberOfRupturesFromSite[n]]++;
            }
        }
        
//        for(int n = 0; n < TotalCellNumber; n++){
//            for(int i=0 ; i<4 ; i++){
//                int neighbour = allCells[n].getNeighbour(i) ;
//                if(neighbour >=0 ) {
//                   if(allCells[n].isCellRuptured() && allCells[neighbour].isCellRuptured()){
//                      if(initialRuptureSite[n]!=initialRuptureSite[neighbour]){
//                          System.out.println(numberOfRupturesFromSite[n] + " " + numberOfRupturesFromSite[neighbour]);
//                      } 
//                   }
//                }
//            }
//        }
        
    }
    
}
