package vnt;
/**
 * Batch_Folder.java - v1.0
 * Began: April 23, 2006
 * Last Updated: April 23, 2006 
 * 
 * Copyright (C) 2005-2006 - Michael D. Miller - mdm162@truman.edu
 * Truman State University
 * 100 E. Normal
 * Kirksville, MO - 63501
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

import ij.*;
import ij.gui.*;
import java.awt.*;
import java.awt.Color.*;
import ij.plugin.PlugIn;
import ij.process.*;
import java.io.*;

import ij.io.*;
import java.lang.String.*;
import java.lang.Math.*;

/**
 * <p>Batch processes an entire folder of images.
 * Batch_Folder will do the following:</p>
 * <ol>
 * <li>grayscale</li>
 * <li>lighting correction</li>
 * <li>segmentation</li>
 * <li>skeletonization</li>
 * <li>endpoint pruning and outline generation</li>
 * <li>perform graph theoretic analysis on the skeleton</li>
 * </ol>
 * 
 * <p>After it is complete, Batch_Folder closes all images.
 * An alternative is Batch_Filde, which will perform this process on only one
 * specific image, but it will leave all the images generated by the process
 * open for user inspection.</p>
 * 
 * @author Michael Miller - Truman State University
 * @version 1.0
 * @since 1.0
 * @see Batch_File
 */
public class Batch_Folder extends VascularNetworkToolkit implements PlugIn {

    /**
     * This is called at the beginning of the PlugIn. 
     *  
     * <p>Pre: ImageJ is open and the plugin was called.
     * <br />Post: A batch process is performed on a selected folder. 
     * @param arg Required by the interface. The argument, if any (may be blank).
     */
    public void run(String arg){    
        // check the ImageJ version
//      if (!IJ.versionLessThan("1.35l")) {
        if (IJ.versionLessThan("1.32")) {
            // ImageJ needs to be updated.
            IJ.showMessage("ImageJ Version Update Needed", "ImageJ needs to be updated to run this plugin.");
            return;
        }

        // create an Open dialogue for the user
        String directoryName = IJ.getDirectory("");
        if (directoryName.length() == 0) {
            // user closed the dialogue
            return;
        }
        // process the folder
        recursiveProcessFolder(directoryName, true);

        return;
    }
    
    private void recursiveProcessFolder(String directoryName, boolean goDeeper) {
        File directory = new File(directoryName);
        FilenameFilter filter = new FilenameFilter() {
            public boolean accept(File directory, String name) {
                if (name.startsWith("."))
                    return false;
                if (name.endsWith(".txt"))
                    return false;
                return true;
            }
        };
        String[] contents = directory.list(filter);     
        if (contents == null) {
            // Either dir does not exist or is not a directory.
            return;
        }

        String filename;
        for (int i=0; i<contents.length; i++) {
            // Get filename of file or directory
            filename = directoryName+contents[i];
            // check if the content is a file or a folder
            if ((new File(filename)).isDirectory()) {
                // if content is a folder, should we recursively explore it?
                if (goDeeper)
                    recursiveProcessFolder(filename+"/", goDeeper);
            } else {
                // content is a file, is it an image?
//              if (getFileInformation(IJ.openImage(filename))) {               
                IJ.open(filename);
                if (getFileInformation(IJ.getImage())) {
                    // we now have an open image and we extracted its settings, analyze it!
                    mainProcess();
                    cleanUpAfterProcess();
                }
            }
        }
        // all done with this folder!
    }
    
    /**
     * This is called when a particular image is open and it needs to be processed. 
     *  
     * <p>Pre: An image is open and ready to be processed by the VNT.
     * <br />Post: A batch process is performed on a currently active image. 
     */
    private void mainProcess() {
        ////////////////////
        // 0) Grayscaling // (and TIFF conversion)
        ////////////////////
        String extlessName = name.substring(0,name.lastIndexOf('.'));
        if (!name.equalsIgnoreCase(extlessName+".tif")) {
            IJ.run("RGB Color");
            IJ.saveAs("tiff", directory+name);
        }
        IJ.run("8-bit");
        IJ.saveAs("tiff", directory+"gray_"+name);
        
        ////////////////////////
        // 1) Light Correction//
        ////////////////////////
        if (performPolynomialLightingCorrection)
            IJ.run("Lighting Correction");
        // Note: This plugin saves a new image as "lightcorrected_"+filename
        
        ////////////////////
        // 2) Segmentation//
        ////////////////////
        if (useHighLowSegmentation)
            IJ.run("Basic Segment");
        else
            IJ.run("FindEdges Segment");
        // Note: This plugin saves a new image as "segmented_"+filename
        
        ///////////////////////
        // 3) Skeletonization//
        ///////////////////////
        IJ.run("DistanceMap Skeleton");
        // Note: This plugin saves a new image as "skeleton_"+filename
        
        ///////////////
        // 4) Pruning//
        ///////////////
        IJ.run("Endpoint Prune");
        // Note: This plugin saves a new image as "pruned_"+filename
        
        ////////////////////////////
        // 4.5) Outline Generation//
        ////////////////////////////
        IJ.run("DistanceMap Outline");
        // Note: This plugin saves a new image as "outline_"+filename
        IJ.run("Close");
        
        ////////////////
        // 5) Analysis//
        ////////////////
        IJ.run("Node Analysis");
        // Note: This plugin saves a new image as "nodes_"+filename
        // Note: This plugin saves a new image as "graph_"+filename
        
        /////////////////////////////
        // 6) Additional Operations//
        /////////////////////////////
        if (performEyeCandy)
            IJ.run("Eye Candy");
    }
    
    /**
     * This is called after a particular image has been processed by the VNT. 
     *  
     * <p>Pre: An image has been opened and processed by the VNT.
     * <br />Post: All open files are closed, and [temp files may be deleted]. 
     */
    private void cleanUpAfterProcess() {
        ////////////////////
        // 0) Grayscaling // (and TIF conversion)
        ////////////////////
        IJ.runMacro("close();");

        ////////////////////////
        // 1) Light Correction//
        ////////////////////////
        if (performPolynomialLightingCorrection) {
            IJ.runMacro("close();");
            IJ.runMacro("close();");
        }
        
        ////////////////////
        // 2) Segmentation//
        ////////////////////
        if (useHighLowSegmentation) {
            IJ.runMacro("close();");
            IJ.runMacro("close();");
            IJ.runMacro("close();");
        } else {
            IJ.runMacro("close();");
            IJ.runMacro("close();");
        }
        
        ///////////////////////
        // 3) Skeletonization//
        ///////////////////////
        IJ.runMacro("close();");
        IJ.runMacro("close();");
        IJ.runMacro("close();");
        
        ///////////////
        // 4) Pruning//
        ///////////////
        IJ.runMacro("close();");
        
        ////////////////////////////
        // 4.5) Outline Generation//
        ////////////////////////////
        
        ////////////////
        // 5) Analysis//
        ////////////////
        IJ.runMacro("close();");
        IJ.runMacro("close();");
        IJ.runMacro("close();");
        
        /////////////////////////////
        // 6) Additional Operations//
        /////////////////////////////
        if (performEyeCandy) {
            IJ.runMacro("close();");
        }

        // compute an extensionless filename
        String extlessName = name.substring(0,name.lastIndexOf('.'));
        // delete all temporary image files
        if (keepTemporaryImageFiles == false) {
            if (!name.equalsIgnoreCase(extlessName+".tif"))
                (new File(directory+extlessName+".tif")).delete();
            (new File(directory+"gray_"+extlessName+".tif")).delete();
            (new File(directory+"lightcorrected_"+extlessName+".tif")).delete();
            if (generateLightingCorrectionSurfaceEyeCandy)
                (new File(directory+"surface_"+extlessName+".tif")).delete();
            (new File(directory+"segmented_"+extlessName+".tif")).delete();
            (new File(directory+"skeleton_"+extlessName+".tif")).delete();
            (new File(directory+"pruned_"+extlessName+".tif")).delete();
            (new File(directory+"outline_"+extlessName+".tif")).delete();
            (new File(directory+"nodes_"+extlessName+".tif")).delete();
            (new File(directory+"graph_"+extlessName+".tif")).delete();
            (new File(directory+"merged_"+extlessName+".tif")).delete();
        }
        // delete all graph text files
        if (keepGraphTextFiles == false) {
            (new File(directory+"coord"+extlessName+".txt")).delete();
            (new File(directory+"skel"+extlessName+".txt")).delete();
        }
        // all done cleaning!
    }
}