package usda.weru.mcrew;

//
//Title:        WEPS XML Management File Updater

//Version:
//Author:       Jim Frankenberger
//Company:      USDA-ARS
//Date:         June 23, 2003
//Description:  Updates WEPS XML management files with the latest crop and operation database records. Also allows names to
//              be fixed with the correct subdirectories for crops and operations.
//
import de.schlichtherle.io.File;
import java.awt.Component;
import java.awt.Frame;
import java.io.FileFilter;

import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Stack;
import java.util.Vector;
import javax.swing.JOptionPane;


import org.apache.log4j.Logger;
import usda.weru.util.WepsFileTypes;

class XMLManagementUpdater implements Runnable {            
    StatusDialog statDialog;
    int finalCount=0;
    Vector <String> tempDb=new Vector <String>();
    Thread mainUpdateThread;
    Component parent;//Reference to the parent window-MCREW
    private static int THREAD_COUNTER;
    //
    // XMLFileFilter
    //
    // Generic class to implement a FilenameFilter to return all files with a specific extension and also
    // to walk down into directories.
    //
    private static class XMLFileFilter implements FilenameFilter {
        String theFilter;

        XMLFileFilter(String filter) {
            theFilter=filter;
        }
        //Accept all directories and all MAN files.
        public boolean accept(java.io.File dir, String name) {
            File f=new File(dir, name);
            if (f.isDirectory()) {
                return true;
            }
            if (name.endsWith("." + theFilter)) {
                return true;
            }
            return false;
//        String fullname="";
//         try {
//            fullname = dir.getCanonicalPath() + "/" + name;
//         } catch (Exception e) {
//                
//         }
//        
//        File f = new File(fullname);
//        if (f.isDirectory()) {
//            return true;
//        }
//      
//        String ext = null;
//        String s = name;
//        int i = s.lastIndexOf('.');
//
//        if (i > 0 &&  i < s.length() - 1) {
//            ext = s.substring(i+1).toLowerCase();
//        }
//        String extension = ext;
//        if (extension != null) {
//            if (extension.equals(theFilter)) {
//               return true;
//            } else {
//                return false;
//            }
//        }
//
//        return false;
//
        }
    }

    //This function just takes the directory , performs recursion, searches for the 
    //desired files, puts them in a vector and returns them.
    public Vector <String> onlyRecursion(String dir, String filterName) {
        Vector  <String> dirVector=new Vector <String>();
        //XMLFileFilter filter = new XMLFileFilter("man");
        XMLFileFilter filter=new XMLFileFilter(filterName);
        File currentDir=new File(dir);

        if (currentDir.isDirectory() == false) {
            JOptionPane.showMessageDialog(null, "Directory is not valid: " + dir, "Error", JOptionPane.INFORMATION_MESSAGE);
            return null;
        }


        /*
        // test it skel directory exists to hold temp files
        File fs = new File(ConfigData.getDirectoryName(XMLConstants.smanagement_skeleton));
        if ((!fs.exists()) || (!fs.isDirectory())) {
        JOptionPane.showMessageDialog(null,"Skeleton directory is not valid: \n\n"+ConfigData.getDirectoryName(XMLConstants.smanagement_skeleton),
        "Error",JOptionPane.INFORMATION_MESSAGE);
        return null;    
        }
         */
        Stack<File> alldirs=new Stack<File>();
        alldirs.push(currentDir);

        // Build a list of the files to process.
        while (alldirs.empty() == false) {
            currentDir=alldirs.pop();

            for (java.io.File f : currentDir.listFiles(filter)) {
                try {
                    String dname=f.getCanonicalPath();
                    if (!f.isDirectory()) {
                        dirVector.addElement(dname);
                    } else {
                        dirVector.addElement(dname);
                        alldirs.push(new File(f));
                    } //end of if-else
                } catch (IOException ex) {
                    Logger.getLogger(XMLManagementUpdater.class).error(ex);
                }
            }//end of for loop
        }//end of while
        return dirVector;
    }//end of onlyRecursion
    /* The method updateDirectory() is called to update all the .man files 
     * in a specific directory, if the recurse flag is set then all management files
     * in any subdirectories are also updated.
     */
    Vector db=new Vector();

    public void updateDirectory(Component parent, String dir, boolean recurse) {
        int count=0;
        this.parent=parent;
        count=doRecursion(dir, recurse);
        if (count != 0) {
            doUpdate(parent, db);
        }

    }//end of method  updateDirectory   
    public int doRecursion(String dir, boolean recurse) {
        
        //XMLFileFilter filter = new XMLFileFilter("man");        
        File currentDir=new File(dir);

        if (currentDir.isDirectory() == false) {
            JOptionPane.showMessageDialog(null, "Directory is not valid: " + dir, "Error", JOptionPane.INFORMATION_MESSAGE);
            return 0;
        }
        
        // test it skel directory exists to hold temp files
        File fs=new File(ConfigData.getDirectoryName(XMLConstants.smanagement_skeleton));
        if ((!fs.exists()) || (!fs.isDirectory())) {
            JOptionPane.showMessageDialog(null, "Skeleton directory is not valid: \n\n" + ConfigData.getDirectoryName(XMLConstants.smanagement_skeleton),
                "Error", JOptionPane.INFORMATION_MESSAGE);
            return 0;
        }
        Stack alldirs=new Stack();
        alldirs.push(currentDir);

        FileFilter filter = new FileFilter() {

            @Override
            public boolean accept(java.io.File file) {
                return file.isDirectory() || WepsFileTypes.Management.accept(file) || WepsFileTypes.Rotation.accept(file);
            }
        };
        
        // Build a list of the files to process.
        while (alldirs.empty() == false) {
            currentDir=(File) alldirs.pop();
            java.io.File fnames[]=currentDir.listFiles(filter);

            for (int i=0; i < fnames.length; i++) {
                try {
                    String dname=fnames[i].getCanonicalPath();
                    if (fnames[i].isDirectory() == false) {
                        db.addElement(dname);
                    } else {
                        if (recurse) {
                            File dirname=new File(dname);
                            alldirs.push(dirname);
                        }
                    }
                } catch (Exception e) {
                //System.out.println("Error: " + e);
                }
            }
        }
        return 1;
    }//end of doRecursion()
    public void doUpdate(Component parent, Vector <String> db) {
        // Process all the files in db vector
        tempDb=db;
        this.parent=parent;
        //  //System.out.println("tempDb.size:"+tempDb.size());
        finalCount=0;
        this.statDialog=new StatusDialog(parent, "Updating Management Files", this);
        this.statDialog.setMaxProgress(db.size());
        this.statDialog.setVisible(true);
        //Add a thread ID to track how many of these we are creating
        mainUpdateThread=new Thread(this, "XML Management Updater-" + THREAD_COUNTER++);
        mainUpdateThread.setPriority(1);
        mainUpdateThread.start();

    }//end of method doUpdate()
    public void run() {
        int count=0;
        String skelfile=ConfigData.getDirectoryName(XMLConstants.smanagement_skeleton) + "\\temp.skel";
        SkelImportPanel skelimport=new SkelImportPanel(null, "Operation or crop not found", true, ManageData.WriteFileMode.UPDATE);
        String opDBDir=ConfigData.getDirectoryName(XMLConstants.soperation);
        String cropDBDir=ConfigData.getDirectoryName(XMLConstants.scrop);        
        if (!skelimport.setDatabases(opDBDir, cropDBDir)){
            //something didn't go right, let's quit
            return;
        }
        int totalFiles=tempDb.size();
        for (int i=0; i < tempDb.size(); i++) {
            String s=(String) tempDb.elementAt(i);

            // convert .man into a skeleton XML file in order to strip out all the crop and operation detail parameters
            SkeletonUpdater skel=new SkeletonUpdater();
            //Update the text field & progress bar in the status dialog
            this.statDialog.JTF_status.setText("Updating " + (i + 1) + " out of " + totalFiles + " Management files.");
            this.statDialog.setProgress(i + 1);
            this.statDialog.refresh();
            // This is what really does the conversion, read the management file and then write it out as a XML skel file
            if (skel.readWEPSManBrief(s)) {
                File manfile=new File(s);
                String basefile=manfile.getName();
                int end=basefile.lastIndexOf(".");
                if (end > 0) {
                    basefile=basefile.substring(0, end);
                }

                // This is a temp file in the skeleton directory with a __ at the beginning og the name
                skelfile=ConfigData.getDirectoryName(XMLConstants.smanagement_skeleton) + File.separator + "__" + basefile + ".skel";
                if (skel.writeSkeletonXMLFile(skelfile)) {
                    // now use the skel-to-man code to build a full file with the updated params
                    if(!skelimport.setDatabases(opDBDir, cropDBDir)){
                        //something didn't go right, let's quit
                        return;
                    }

                    // If there are operation or crop database files that are not found allow the user to fix these
                    if (skelimport.skel2man(skelfile, s)) {
                        count++;

                    } else {
                        if (JOptionPane.showConfirmDialog(parent, "Do you want to stop updating management files?", "WEPS Information", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                            File tempSkelFile=new File(skelfile);
                            if (tempSkelFile.exists()) {
                                tempSkelFile.delete();
                            }    // cleanup the intermediate step
                            break;
                        }
                    }//end of inner if-else block
                } else {
                    if (JOptionPane.showConfirmDialog(parent, "Could not load skeleton file: " + skelfile + "\n\nDo you want to stop updating management files?", "WEPS Information", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                        break;
                    }
                }

                File tempSkelFile=new File(skelfile);
                if (tempSkelFile.exists()) {
                    tempSkelFile.delete();
                }    // cleanup the skel file used in the intermediate step
            }//end of if(skel.readWEPSManBrief(s))
        }//end of for loop
        finalCount=count;
        //dispose of the status dialog
        statDialog.setVisible(false);
        statDialog.dispose();
        statDialog=null;
        //Display the total number of files updated.
        JOptionPane.showMessageDialog(parent, finalCount + " WEPS Management Files Updated", "WEPS Information", JOptionPane.INFORMATION_MESSAGE);

    }//end of run method
}//end of class XMLManagementUpdater

/* This class handles the behavior of the Status dialog.
 * This is the wrapper for the window that tracks the progress
 * of the update of the Management Files.
 ** @author  neha
 */
class StatusDialog extends usda.weru.mcrew.gui.StatusDialog_n {
    XMLManagementUpdater xmlMgmt;

    /** Creates a new instance of StatusDialog */
    public StatusDialog(Component parent, String title, XMLManagementUpdater xmlMgmtUpdater) {
        super((Frame) parent, false);
        this.xmlMgmt=xmlMgmtUpdater;
        setModal(false);
        setTitle(title);
        setLocation(100, 100);
        setVisible(true);
        JTF_status.setVisible(true);
        JPB_mcrew.setVisible(true);
        setVisible(true);
    }

    /*set the max number of files for the JProgressBar 
     *@param max
     */
    public void setMaxProgress(int max) {
        JPB_mcrew.setMaximum(max);
    }//end of setMaxProgress()
    public void setProgress(int current) {
        JPB_mcrew.setValue(current);
    }//end of setProgress
    public void setExpr(String expr) {
        JTF_status.setText(expr);
    }//end of setExpr
    public void refresh() {
        JP_main.revalidate();
    }
}//end of class StatusDialog

