package usda.weru.mcrew;

import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileReader;
import de.schlichtherle.truezip.file.TFileWriter;
import de.schlichtherle.truezip.file.TVFS;
import de.schlichtherle.truezip.fs.FsSyncException;
import java.awt.Cursor;
import java.awt.HeadlessException;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Stack;
import java.util.Vector;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javolution.context.Context;
import org.apache.log4j.Logger;
import org.openide.util.Exceptions;
import usda.weru.util.Util;
import usda.weru.util.WepsFileChooser;
import usda.weru.util.WepsFileTypes;
import usda.weru.util.WepsMessageDialog;

/**
 * This class was split off from the MCREW window to save lines and increase clarity.
 * @author jonathanhornbaker
 */
public class SkelManConverter 
{
    private MCREWWindow source;
    /**
     * These two directory names are used in the recursive conversion of skeleton files to WEPS
     * Management files and vice versa. This is the source directory tfrom where we can get the
     * files for conversion.
     */
    private String sourceDirName = null;
    /**
     * Directory name is used in recursive conversion of skeleton files to WEPS Management file and
     * vice versa. This is the target directory that stores the converted files.
     */
    private String targetDirName = null;
    private static final Logger LOGGER = Logger.getLogger(TablePanel.class);
    /**
     * These constants allow convertRec() method to differentiate between the 2 types of
     * conversions. Here - WEPS Management file to Skeleton files.
     */
    public static final int MAN2SKELREC = 0;
    /**
     * These constants allow convertRec() method to differentiate between the 2 types of
     * conversions. Here - Skeleton files to WEPS Management files. Similar to the above on .. but
     * just opposite way conversion.
     */
    public static final int SKEL2MANREC = 1;
    
    
    public SkelManConverter(MCREWWindow wind)
    {
        source = wind;
    }
    
    /**
     * Converts a WEPS management file into an XML skeleton file.
     * @param event
     * @param singleFileOnly 
     */
    public void ManToSkel(java.awt.event.ActionEvent event, boolean singleFileOnly) {
        try {
            // Step 1: Prompt for the source .man files to convert
            String m_fileName = "";
            String skelfile = "";
            String skelfileShort = "";
            String fileNameShort = "";
            Vector<String> createdFiles = new Vector<>();

            WepsFileChooser fileChooser = new WepsFileChooser(WepsFileChooser.Filetype.FILE, "", WepsFileChooser.SELECT);
            fileChooser.setFileSelectionMode(WepsFileChooser.FILES_ONLY);
            if (singleFileOnly == false) {
                fileChooser.setMultiSelectionEnabled(true);
                fileChooser.setAcceptAllFileFilterUsed(false);
                fileChooser.setApproveButtonText("Select Files");
            } else {
                fileChooser.setMultiSelectionEnabled(false);
                fileChooser.setApproveButtonText("Choose File");
            }

            XMLSkelFilter filter = new XMLSkelFilter("man", "WEPS Management Files");
            fileChooser.setFileFilter(filter);
            fileChooser.setDialogTitle("Select a WEPS management file");

            String dir = MCREWConfig.getDirectoryName(XMLConstants.smanagement_template);
            TFile ddir = new TFile(dir);
            fileChooser.setCurrentDirectory(ddir);

            java.io.File[] sourceFiles = null;

            int returnVal = fileChooser.showOpenDialog(source);

            if (returnVal == WepsFileChooser.APPROVE_OPTION) {
                try {
                    // depending on whether multiple selection is enabled java uses 2 different calls to get the
                    // selected file(s).
                    if (singleFileOnly == false) {
                        sourceFiles = fileChooser.getSelectedFiles();
                    } else {
                        sourceFiles = new TFile[1];
                        sourceFiles[0] = fileChooser.getSelectedFile();
                    }
                } catch (Exception e) {
                    System.err.println("Error: " + e);
                }
            } else {
                return;
            }
            boolean doConversion = true;
            for (java.io.File sourceFile : sourceFiles) {
                try {
                    m_fileName = sourceFile.getCanonicalPath();
                    doConversion = isManFile(m_fileName);
                    if (doConversion == false) {
                        JOptionPane.showMessageDialog(source, m_fileName
                                + "\n\nSelection is not a WEPS .man file.\n\nNo Files Converted.", "WEPS Information",
                                JOptionPane.ERROR_MESSAGE);
                    }
                } catch (IOException | HeadlessException e) {
                    System.err.println("Error: " + e);
                }
            }

            if (doConversion == false) {
                return;
            }

            WepsFileChooser fileChooserMan = new WepsFileChooser(WepsFileChooser.Filetype.FILE, "", WepsFileChooser.SELECT);
            if (singleFileOnly == false) {
                fileChooserMan.setFileSelectionMode(WepsFileChooser.DIRECTORIES_ONLY);
                fileChooserMan.setMultiSelectionEnabled(false);
                fileChooserMan.setDialogTitle("Select a destination directory where the NRCS XML files will be created");
                fileChooserMan.setAcceptAllFileFilterUsed(false);
                fileChooserMan.setApproveButtonText("Choose Directory");
            } else {
                fileChooserMan.setFileSelectionMode(WepsFileChooser.FILES_ONLY);
                fileChooserMan.setDialogTitle("Select a destination ");
                fileChooserMan.setApproveButtonText("Choose File");
                fileChooserMan.setApproveButtonToolTipText("Select a NRCS XML file to be created");
                fileChooserMan.setAcceptAllFileFilterUsed(true);
                XMLSkelFilter filterMan = new XMLSkelFilter("skel", "NRCS XML Management Files(*.skel)");
                fileChooserMan.setFileFilter(filterMan);
                String targetfile = sourceFiles[0].getName();

                targetfile = Util.purgeExtensions(targetfile, ".man", ".skel") + ".skel";

                TFile target = new TFile(targetfile);
                fileChooserMan.setSelectedFile(target);
            }

            dir = MCREWConfig.getDirectoryName(XMLConstants.smanagement_skeleton);
            ddir = new TFile(dir);

            String skeldir = "";
            fileChooserMan.setCurrentDirectory(ddir);

            returnVal = fileChooserMan.showOpenDialog(source);
            if (returnVal == WepsFileChooser.APPROVE_OPTION) {
                try {
                    if (singleFileOnly == false) {
                        skeldir = fileChooserMan.getSelectedFile().getCanonicalPath() + TFile.separator;
                        TFile testdir = new TFile(skeldir);
                        if ((!testdir.exists()) || testdir.isFile()) {
                            JOptionPane.showMessageDialog(source, skeldir
                                    + "\n\nSelection is not a directory.", "WEPS Information",
                                    JOptionPane.ERROR_MESSAGE);
                            return;
                        }
                    } else {
                        skelfile = fileChooserMan.getSelectedFile().getCanonicalPath() + TFile.separator;
                        TFile testFile = new TFile(skelfile);
                        if (testFile.isDirectory()) {
                            JOptionPane.showMessageDialog(source, skelfile + "\n\nSelection is not a file.", "WEPS Information",
                                    JOptionPane.ERROR_MESSAGE);
                            return;
                        }
                    }
                } catch (HeadlessException | IOException e) {
                    System.err.println("Error: " + e);
                }
            } else {
                return;
            }
            int total = 0;
            for (java.io.File sourceFile : sourceFiles) {
                if (singleFileOnly == false) {
                    skelfile = Util.purgeExtensions(skeldir + sourceFile.getName(), ".man", ".skel") + ".skel";
                } else {
                    TFile shortName = new TFile(skelfile);

                    int end = shortName.getName().lastIndexOf(".");
                    if (end == -1) {
                        skelfile = skelfile + ".skel";
                    }
                }
                try {
                    m_fileName = sourceFile.getCanonicalPath();
                    fileNameShort = sourceFile.getName();
                } catch (IOException e) {
                    System.err.println("Error: " + e);
                }
                if (doConversion) {
                    TFile f = new TFile(skelfile);
                    skelfileShort = f.getName();

                    //System.out.println("Checking: "+skelfile);
                    if (f.exists()) {
                        if (JOptionPane.showConfirmDialog(source, "Destination file already exists. \nDo you want to overwrite "
                                + skelfileShort + "?", "File Exists", JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
                            doConversion = false;
                        }
                    }
                    if (doConversion) {
                        SkeletonUpdater skel = new SkeletonUpdater();

                        // This is what really does the conversion, read the management file and then write it out
                        // as a XML skel file
                        if (skel.readWEPSManBrief(m_fileName)) {
                            if (skel.writeSkeletonXMLFile(skelfile)) {
                                createdFiles.addElement(skelfile);
                                total++;
                            } else {
                                System.out.println("Could not write skelfile: " + skelfile + "\n");
                            }
                        } else {
                            System.out.println("Could not read: " + m_fileName + "\n");
                        }
                    } else {
                        System.out.println("Do conversion reset?\n");
                    }
                } else {
                    System.out.println("Do conversion=false\n");
                }
            }

            if (singleFileOnly == true) {
                JOptionPane.showMessageDialog(source, "WEPS NRCS XML file created:\n" + skelfile, "WEPS Information",
                        JOptionPane.INFORMATION_MESSAGE);
            } else {
                if (total >= 1) {
                    JTextArea info = new JTextArea(10, 35);
                    JScrollPane js = new JScrollPane(info);
                    for (int i = 0; i < total; i++) {
                        info.append(createdFiles.elementAt(i) + "\n");
                    }
                    JOptionPane.showMessageDialog(source, js, total + " WEPS NRCS XML Management Files Created",
                            JOptionPane.INFORMATION_MESSAGE);
                }
            }
            TVFS.umount();
        } catch (FsSyncException ex) {
            java.util.logging.Logger.getLogger(TablePanel.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /** 
     * Converts an NRCS skeleton XML file into a full WEPS management file.
     * This also gives the user the option of resolving unknown crops or operations.
     * @param event
     * @param singleFileOnly 
     */
    public void SkelToMan(java.awt.event.ActionEvent event, boolean singleFileOnly) {
        try {
            // Step 1: Prompt for the source .XML/SKEL file that will be converted
            String fromFileName = "";
            String toPath = "";
            String manfileShort = "";
            String fileNameShort = "";
            Vector<String> createdFiles = new Vector<>();

            WepsFileChooser fileChooser = new WepsFileChooser(WepsFileChooser.Filetype.FILE, "", WepsFileChooser.SELECT);
            fileChooser.setFileSelectionMode(WepsFileChooser.FILES_ONLY);
            if (singleFileOnly == false) {
                fileChooser.setMultiSelectionEnabled(true);
                fileChooser.setApproveButtonText("Select Files");
            } else {
                fileChooser.setMultiSelectionEnabled(false);
            }
            XMLSkelFilter filter = new XMLSkelFilter("skel", "NRCS XML Skeleton Management Files(*.skel)");
            fileChooser.setFileFilter(filter);
            fileChooser.setDialogTitle("Select an NRCS skeleton XML management file");

            String dir = MCREWConfig.getDirectoryName(XMLConstants.smanagement_skeleton);
            TFile ddir = new TFile(dir);
            fileChooser.setCurrentDirectory(ddir);

            int returnVal = fileChooser.showOpenDialog(source);
            java.io.File[] sourceFiles = null;

            if (returnVal == WepsFileChooser.APPROVE_OPTION) {
                try {
                    if (singleFileOnly == false) {
                        sourceFiles = fileChooser.getSelectedFiles();
                    } else {
                        sourceFiles = new TFile[1];
                        sourceFiles[0] = fileChooser.getSelectedFile();
                    }
                } catch (Exception e) {
                    System.err.println("Error: " + e);
                }
            } else {
                return;
            }
            WepsFileChooser fileChooserMan = new WepsFileChooser(WepsFileChooser.Filetype.FILE, "", WepsFileChooser.SELECT);
            fileChooserMan.setMultiSelectionEnabled(false);
            if (singleFileOnly == false) {
                // Step 2: Have user select the WEPS management directory where the files will be written
                fileChooserMan.setFileSelectionMode(WepsFileChooser.DIRECTORIES_ONLY);
                fileChooserMan.setDialogTitle("Select a destination WEPS management directory where the files will be created");
                fileChooserMan.setApproveButtonText("Choose Directory");
                fileChooserMan.setApproveButtonToolTipText("Select a destination WEPS management directory "
                        + "where the files will be created");
                fileChooserMan.setAcceptAllFileFilterUsed(false);
            } else {
                fileChooserMan.setDialogTitle("Select a destination WEPS management file that will be created");
                fileChooserMan.setApproveButtonText("Choose File");
                fileChooserMan.setApproveButtonToolTipText("Select a destination WEPS management file where to be created");
                fileChooserMan.setAcceptAllFileFilterUsed(true);
                XMLSkelFilter filterMan = new XMLSkelFilter("man", "WEPS Management Files(*.man)");
                fileChooserMan.setFileFilter(filterMan);
                String targetfile = sourceFiles[0].getName();

                if (targetfile.endsWith(".skel")) {
                    targetfile = Util.purgeExtensions(targetfile, ".man", ".skel") + ".man";
                } else {
                    targetfile = Util.purgeExtensions(targetfile, ".man", ".skel") + ".skel";
                }
                TFile target = new TFile(targetfile);
                fileChooserMan.setSelectedFile(target);
            }

            dir = MCREWConfig.getDirectoryName(XMLConstants.smanagement_template);
            ddir = new TFile(dir);

            String mandir = "";

            fileChooserMan.setCurrentDirectory(ddir);

            returnVal = fileChooserMan.showOpenDialog(source);
            if (returnVal == WepsFileChooser.APPROVE_OPTION) {
                try {
                    if (singleFileOnly == false) {
                        mandir = fileChooserMan.getSelectedFile().getCanonicalPath() + TFile.separator;
                        TFile testdir = new TFile(mandir);
                        if ((!testdir.exists()) || testdir.isFile()) {
                            JOptionPane.showMessageDialog(source, mandir + "\n\nSelection is not a directory.",
                                    "WEPS Information", JOptionPane.ERROR_MESSAGE);
                            return;
                        }
                    } else {
                        toPath = fileChooserMan.getSelectedFile().getCanonicalPath() + TFile.separator;
                        TFile testFile = new TFile(toPath);
                        if (testFile.isDirectory()) {
                            JOptionPane.showMessageDialog(source, toPath + "\n\nSelection is not a file.",
                                    "WEPS Information", JOptionPane.ERROR_MESSAGE);
                            return;
                        }
                    }
                } catch (HeadlessException | IOException e) {
                    System.err.println("Error: " + e);
                }
            } else {
                return;
            }
            SkelImportPanel skelimport = new SkelImportPanel(source, "Operation or crop not found",
                    true, ManageData.WriteFileMode.FROM_NRCS);

            String opDBDir = MCREWConfig.getDirectoryName(XMLConstants.soperation);
            String cropDBDir = MCREWConfig.getDirectoryName(XMLConstants.scrop);

            if (!skelimport.setDatabases(opDBDir, cropDBDir)) {
                //something went wrong, quit
                return;
            }

            //
            // Loop through each of the skeleton files and convert them to a full weps management file.
            //
            int total = 0;
            String newstr = "";
            boolean overwriteAll = false;
            boolean skipAll = false;
            Stack<ConversionTask<TFile>> stack = new Stack<ConversionTask<TFile>>();
            for (java.io.File from : sourceFiles) {
                if (singleFileOnly == false) {
                    //TODO: rot extension
                    toPath = mandir + Util.purgeExtensions(from.getName(), ".man", ".skel") + ".man";
                } else {
                    TFile shortName = new TFile(toPath);

                    int end = shortName.getName().lastIndexOf(".");
                    if (end == -1) {
                        toPath = toPath + ".man";
                    }
                }

                TFile to = new TFile(toPath);

                stack.push(new ConversionTask<TFile>(new TFile(from), new TFile(to)));
            }

            ConversionContext.enter(stack);
            try {
                int popped = 0;
                while (!stack.empty()) {

                    skelimport.setProgress(popped, popped + stack.size());

                    ConversionTask<TFile> task = stack.pop();
                    ConversionContext.getCurrent().task = task;
                    popped++;

                    TFile fromFile = task.getFrom();
                    TFile toFile = task.getTo();

                    manfileShort = toFile.getName();

                    try {
                        fromFileName = fromFile.getCanonicalPath();
                        fileNameShort = toFile.getName();
                    } catch (IOException e) {
                        System.err.println("Error: " + e);
                    }

                    boolean doconversion = true;
                    while (toFile.exists() && !overwriteAll && !skipAll) {
                        String[] options = {"Overwrite", "Overwrite All", "Rename", "Skip", "Skip All"};
                        int result = JOptionPane.showOptionDialog(source,
                                "Destination management file already exists.\n" + toFile.getName(),
                                "File Exists", 0, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
                        if (result == 0) {
                            //overwrite the file.
                            doconversion = true;
                            break;
                        } else if (result == 1) {
                            //overwrite all
                            doconversion = true;
                            overwriteAll = true;
                            break;
                        } else if (result == 2) {
                            //select a new file name.
                            //show the proper file chooser based on if toFile is man or rot!
                            WepsFileChooser wfc;
                            if (WepsFileTypes.Management.accept(toFile)) {
                                wfc = WepsFileChooser.create(WepsFileChooser.Action.Create,
                                        new TFile(toFile.getParentFile()), WepsFileTypes.Management);
                            } else {
                                wfc = WepsFileChooser.create(WepsFileChooser.Action.Create,
                                        new TFile(toFile.getParentFile()), WepsFileTypes.Rotation);
                            }

                            wfc.setSelectedFile(toFile);
                            wfc.setPersitSelectedFile(false);
                            if (wfc.showDialog(source) == WepsFileChooser.APPROVE_OPTION) {
                                toPath = wfc.getSelectedFile().getPath();
                                toFile = new TFile(wfc.getSelectedFile());

                                //upate the current task
                                task.to = toFile;
                            }
                        } else if (result == 3) {
                            //skip
                            doconversion = false;
                            break;
                        } else if (result == 4) {
                            //skip all
                            skipAll = true;
                            doconversion = false;
                            break;
                        }
                    }

                    if (toFile.exists() && overwriteAll) {
                        doconversion = true;
                    }
                    if (toFile.exists() && skipAll) {
                        doconversion = false;
                    }
                    if (doconversion) {
                        if (skelimport.skel2man(fromFileName, toFile.getAbsolutePath())) {
                            total++;
                            createdFiles.addElement(toFile.getAbsolutePath());
                        }
                    }
                }
            } finally {
                ConversionContext.exit();
            }

            if (singleFileOnly == true) {
                JOptionPane.showMessageDialog(source, total + " WEPS management files written to:\n\n "
                        + toPath, "WEPS Information", JOptionPane.INFORMATION_MESSAGE);
            } else {
                if (total >= 1) {
                    JTextArea info = new JTextArea(10, 35);
                    info.setEditable(false);
                    JScrollPane js = new JScrollPane(info);
                    for (int i = 0; i < total; i++) {
                        info.append(createdFiles.elementAt(i) + "\n");
                    }
                    JOptionPane.showMessageDialog(source, js, total
                            + " WEPS Management Files Created", JOptionPane.INFORMATION_MESSAGE);
                }
            }
            logUnknownOperationsAndCrops(skelimport, null);
            TVFS.umount();
        } catch (FsSyncException ex) {
            java.util.logging.Logger.getLogger(TablePanel.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /**
     * called when user requests conversion of WEPS Management files to NRCS XML format recursively.- added by Neha
     * @param evt 
     */
    public void ManToSkelRec(java.awt.event.ActionEvent evt) {

        if (!convertRec(MAN2SKELREC)) {
            return;
        }
        //set the cursor to wait cursor on the Mcrew screen
        source.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

        XMLManagementUpdater updater = new XMLManagementUpdater();
        //Get all the man files in source directory
        List<String> manFiles = updater.onlyRecursion(sourceDirName, "man");

        LOGGER.trace("files to convert:");
        for (int i = 0; manFiles != null && i < manFiles.size(); i++) {
            LOGGER.trace(manFiles.get(i));
        }

        if (manFiles == null) {
            manFiles = Collections.emptyList();
        }
        targetDirName = targetDirName != null ? targetDirName : "";
        sourceDirName = sourceDirName != null ? sourceDirName : "";
        int returnCode = convertToManOrSkelRec(sourceDirName, targetDirName,
                manFiles, MAN2SKELREC, ManageData.WriteFileMode.NORMAL);
        if (returnCode == 0) {
            LOGGER.error("Error in the path of the management directory. Management directory MUST be in db/man");
        } else if (returnCode == 2) {
            LOGGER.debug("User pressed cancel all button");
        } else if (returnCode == 3) {
            LOGGER.error("Error in selecting the target directory");
        } else if (returnCode == 4) {
            LOGGER.error("Error in value of type variable");
        } else if (returnCode == 5) {
            LOGGER.error("Could not write Skeleton file");
        } else if (returnCode == 6) {
            LOGGER.error("Could not read the Management file");
        }

        //set the cursor back to default on the Mcrew screen
        source.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    } //end of ManToSkelRec_actionPerformed

    /**
     * This method handles the WepsFileChooser stuff for the recursive conversion
     * of ManToSkel and SkelToMan - added by Neha
     * @param type
     * @return 
     */
    boolean convertRec(int type) {
        String sourceDir;
        String dir;
        String targetDir = "";
        WepsFileChooser fileChooserSkel = new WepsFileChooser(WepsFileChooser.Filetype.FILE, "", WepsFileChooser.SELECT);
        fileChooserSkel.setFileSelectionMode(WepsFileChooser.DIRECTORIES_ONLY);
        fileChooserSkel.setMultiSelectionEnabled(false);

        fileChooserSkel.setAcceptAllFileFilterUsed(false);
        if (type == 0) {
            fileChooserSkel.setDialogTitle("Select a directory where all WEPS management "
                    + "files are to be converted to Skeleton Management files");
            sourceDir = MCREWConfig.getDirectoryName(XMLConstants.smanagement_template);
        } else if (type == 1) {
            fileChooserSkel.setDialogTitle("Select a directory where all Skeleton management "
                    + "files are to be converted to Weps Management files");
            sourceDir = MCREWConfig.getDirectoryName(XMLConstants.smanagement_skeleton);
        } else {
            return false;
        }
        TFile ddir = new TFile(sourceDir);

        fileChooserSkel.setApproveButtonText("Choose Directory");
        fileChooserSkel.setCurrentDirectory(ddir);

        int returnVal = fileChooserSkel.showOpenDialog(source);
        if (returnVal == WepsFileChooser.APPROVE_OPTION) {
            try {
                sourceDir = fileChooserSkel.getSelectedFile().getCanonicalPath() + TFile.separator;
                TFile testdir = new TFile(sourceDir);
                if ((!testdir.exists()) || testdir.isFile()) {
                    JOptionPane.showMessageDialog(source, sourceDir
                            + "\n\nSelection is not a directory.", "WEPS Information", JOptionPane.ERROR_MESSAGE);
                    return false;
                }
            } catch (HeadlessException | IOException e) {
                System.err.println("Error: " + e);
            }
        } else {
            return false;
        }

        // Step 2: Have user select the destination directory where the files will be written
        WepsFileChooser fileChooserMan = new WepsFileChooser(WepsFileChooser.Filetype.FILE, "", WepsFileChooser.SELECT);
        fileChooserMan.setMultiSelectionEnabled(false);
        fileChooserMan.setFileSelectionMode(WepsFileChooser.DIRECTORIES_ONLY);
        fileChooserMan.setApproveButtonText("Choose Directory");
        fileChooserMan.setAcceptAllFileFilterUsed(false);

        if (type == 0) {
            fileChooserMan.setDialogTitle("Select a destination directory where the Skeleton Management files will be created");
            fileChooserMan.setApproveButtonToolTipText("Select a destination directory where the "
                    + "Skeleton Management files will be created");
            dir = MCREWConfig.getDirectoryName(XMLConstants.smanagement_skeleton);
        } else if (type == 1) {
            fileChooserMan.setDialogTitle("Select a destination WEPS management directory where the files will be created");
            fileChooserMan.setApproveButtonToolTipText("Select a destination WEPS management "
                    + "directory where the files will be created");
            dir = MCREWConfig.getDirectoryName(XMLConstants.smanagement_template);
        } else {
            return false;
        }

        TFile mdir = new TFile(dir);
        fileChooserMan.setCurrentDirectory(mdir);

        returnVal = fileChooserMan.showOpenDialog(source);
        if (returnVal == WepsFileChooser.APPROVE_OPTION) {
            try {
                targetDir = fileChooserMan.getSelectedFile().getCanonicalPath() + TFile.separator;
                TFile testdir = new TFile(targetDir);
                if ((!testdir.exists()) || testdir.isFile()) {
                    JOptionPane.showMessageDialog(source, targetDir + "\n\nSelection is not a directory.",
                            "WEPS Information", JOptionPane.ERROR_MESSAGE);
                    return false;
                }
            } catch (HeadlessException | IOException e) {
                System.err.println("Error: " + e);
            }
        } else {
            return false;
        }
        sourceDirName = sourceDir;
        targetDirName = targetDir;
        //System.out.println("Mcrew:convertRec:sourceDirName:"+sourceDirName);
        //System.out.println("Mcrew:convertRec:targetDirName:"+targetDirName);
        return true;
    } //end of convertRec method

    /**
     * called when user has requested to convert NRCS XML Management files into WEPS format recursively.
     * 
     * @param evt 
     */
    public void SkelToManRec_actionPerformed(java.awt.event.ActionEvent evt) {
        if (!convertRec(SKEL2MANREC)) {
            return;
        }
        //set the cursor to wait cursor on the Mcrew screen
        source.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

        XMLManagementUpdater updater = new XMLManagementUpdater();
        //Get all the skel files in source directory
        List<String> skelFiles = updater.onlyRecursion(sourceDirName, "skel");
        LOGGER.trace("Files to convert:");
        for (int i = 0; skelFiles != null && i < skelFiles.size(); i++) {
            LOGGER.trace(skelFiles.get(i));
        }

        if (skelFiles == null) {
            skelFiles = Collections.emptyList();
        }

        targetDirName = targetDirName != null ? targetDirName : "";
        sourceDirName = sourceDirName != null ? sourceDirName : "";
        int returnCode = convertToManOrSkelRec(sourceDirName, targetDirName, skelFiles,
                SKEL2MANREC, ManageData.WriteFileMode.FROM_NRCS);
        switch (returnCode) {
            case 0:
                LOGGER.error("error in the path of the skeleton directory. skeleton dir MUST be in db/skel");
                break;
            case 2:
                LOGGER.debug("User pressed cancel all button");
                break;
            case 3:
                LOGGER.error("Error in selecting the target directory");
                break;
            case 4:
                LOGGER.error("Error in value of type variable");
                break;
            default:
                break;
        }

        //set the cursor back to default on the Mcrew screen
        source.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));

        //JOptionPane.showMessageDialog(null,files+" NRCS XML skeleton Files converted to WEPS management files",
        //"WEPS Information",JOptionPane.INFORMATION_MESSAGE);
    }

    /**
     * This method takes the skeleton/Management files vector and converts them 
     * into management/ skeleton files - added by Neha
     * @param sourceDir
     * @param targetDir
     * @param srcFiles
     * @param type
     * @param mode
     * @return 
     */
    int convertToManOrSkelRec(String sourceDir, String targetDir, List<String> srcFiles,
            int type, ManageData.WriteFileMode mode) {

        int total = 0;
        String newstr;
        String targetFile_newPath;

        List<String> onlyDirs = new Vector<String>();
        List<String> onlySourceFiles = new Vector<String>();
        List<String> onlyTargetFiles = new Vector<String>();
        List<TFile> createdFiles = new Vector<TFile>();

        SkelImportPanel skelimport = new SkelImportPanel(source, "Operation or crop not found", true, mode);
        String opDBDir = MCREWConfig.getDirectoryName(XMLConstants.soperation);
        String cropDBDir = MCREWConfig.getDirectoryName(XMLConstants.scrop);

        if (!skelimport.setDatabases(opDBDir, cropDBDir)) {
            //something went wrong
            return 0;
        }

        //System.out.println("sourceDir:"+sourceDir+"  targetDir:"+targetDir);
        //We need to get one directory level above that specified in the sourceDir
        //path so that the entire directory structure will be created - neha
        //get rid of the final '\' in the sourceDir path if present
        if (sourceDir.endsWith("\\")) {
            sourceDir = sourceDir.substring(0, sourceDir.length() - 1);
        }
        //Go one directory level above the given path and keep the '\' at the end of the path
        int finalIndex = Math.max(sourceDir.lastIndexOf("\\"), sourceDir.lastIndexOf("/"));
        sourceDir = sourceDir.substring(0, finalIndex + 1);
        for (String entry : srcFiles) {
            int pathEnd = sourceDir.length();

            int entryLength = entry.length();
            String entryNewPath = targetDir + entry.substring(pathEnd, entryLength);
            //System.out.println("MCrew:ConvertToManOrSkelRec:entryNewPath:"+entryNewPath);
            boolean skelOrmanFile = false;
            if (type == 0) {
                skelOrmanFile = entry.endsWith(".man");
            } else if (type == 1) {
                skelOrmanFile = entry.endsWith(".skel");
            } else {
                return 4;
            }
            if (skelOrmanFile == false) {
                onlyDirs.add(entryNewPath);
            } else {
                int end = 0;
                //Remove all *.man and *.skel extensions from the source file
                newstr = Util.purgeExtensions(entryNewPath, ".skel", ".man", ".rot");

                if (type == 0) {
                    targetFile_newPath = newstr + ".skel";
                    onlySourceFiles.add(entry); //source man files
                    onlyTargetFiles.add(targetFile_newPath); //destination skeleton files
                } else if (type == 1) {
                    targetFile_newPath = newstr + ".man";
                    onlyTargetFiles.add(targetFile_newPath); //destination man files
                    onlySourceFiles.add(entry); //source skeleton files
                } else {
                    return 4;
                }
            } //end of else
        }
        //do the conversion from source [skeleton or man] files to target [man or skeleton] files
        boolean overwriteAll = false;
        boolean skipAll = false;
        boolean doconversion = true;

        //prepare conversion stack
        Stack<ConversionTask<TFile>> stack = new Stack<ConversionTask<TFile>>();
        for (int i = 0; i < onlySourceFiles.size(); i++) {
            stack.push(new ConversionTask<TFile>(new TFile(onlySourceFiles.get(i)), new TFile(onlyTargetFiles.get(i))));
        }

        ConversionContext.enter(stack);
        try {
            int popped = 0;
            while (!stack.empty()) {
                skelimport.altPicked = true;

                skelimport.setProgress(popped, popped + stack.size());

                ConversionTask<TFile> task = stack.pop();
                ConversionContext.getCurrent().task = task;
                popped++;

                TFile fromFile = task.getFrom();
                TFile toFile = task.getTo();

                popped++;

                String toPath = toFile.getAbsolutePath();

                LOGGER.debug("Converting: " + (popped) + "/" + stack.size());

                while (toFile.exists() && !overwriteAll && !skipAll) {
                    String[] options = {"Overwrite", "Overwrite All Existing", "Rename", "Skip", "Skip All Existing"};
                    int result = JOptionPane.showOptionDialog(source,
                            "Destination management file already exists.\n" + toFile.getName(),
                            "File Exists", 0, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
                    if (result == 0) {
                        //overwrite the file.
                        doconversion = true;
                        break;
                    } else if (result == 1) {
                        //overwrite all
                        doconversion = true;
                        overwriteAll = true;
                        break;
                    } else if (result == 2) {
                        //select a new file name.
                        WepsFileChooser wfc;
                        if (WepsFileTypes.Management.accept(toFile)) {
                            wfc = WepsFileChooser.create(WepsFileChooser.Action.Create,
                                    new TFile(toFile.getParentFile()), WepsFileTypes.Management);
                        } else if (WepsFileTypes.Rotation.accept(toFile)) {
                            wfc = WepsFileChooser.create(WepsFileChooser.Action.Create,
                                    new TFile(toFile.getParentFile()), WepsFileTypes.Rotation);
                        } else {
                            wfc = WepsFileChooser.create(WepsFileChooser.Action.Create,
                                    new TFile(toFile.getParentFile()), WepsFileTypes.Skeleton);
                        }

                        TFile file = new TFile(toPath);
                        file = Util.incrementFileName(file);
                        wfc.setSelectedFile(file);
                        wfc.setPersitSelectedFile(false);
                        if (wfc.showDialog(source) == WepsFileChooser.APPROVE_OPTION) {
                            toFile = new TFile(wfc.getSelectedFile());
                            toPath = toFile.getAbsolutePath();
                            //upate the current task
                            task.to = toFile;
                        }
                    } else if (result == 3) {
                        //skip
                        doconversion = false;
                        break;
                    } else if (result == 4) {
                        //skip all
                        skipAll = true;
                        doconversion = false;
                        break;
                    }
                }

                if (!toFile.exists()) {
                    doconversion = true;
                } else if (toFile.exists() && overwriteAll) {
                    doconversion = true;
                } else if (toFile.exists() && skipAll) {
                    doconversion = false;
                }
                if (doconversion) {
                    if (type == 0) {
                        SkeletonUpdater skel = new SkeletonUpdater();
                        // This is what really does the conversion, read the management file and
                        // then write it out as a XML skel file
                        if (skel.readWEPSManBrief(fromFile.getAbsolutePath())) {
                            if (skel.writeSkeletonXMLFile(toFile.getAbsolutePath())) {
                                createdFiles.add(toFile);
                                total++;
                            } else {
                                logUnknownOperationsAndCrops(skelimport, null);
                                return 5;
                            }
                        } else {
                            logUnknownOperationsAndCrops(skelimport, null);
                            return 6;
                        }
                    } else if (type == 1) {
                        if (skelimport.skel2man(fromFile.getAbsolutePath(), toFile.getAbsolutePath())) {
                            Logger.getLogger(TablePanel.class).debug("Converting file: " + fromFile);
                            total++;
                            createdFiles.add(toFile);
                        } else {
                            Logger.getLogger(TablePanel.class).error("Could not convert Skel file: " + fromFile);
                        }
                    } else {
                        logUnknownOperationsAndCrops(skelimport, null);
                        return 4;
                    }
                } //end of if(doconversion) loop
                if (skelimport.skipRemainingFlag) {
                    //User is skipping the remaining files.
                    Logger.getLogger(TablePanel.class).info("Skipping remaining files.");
                    break;
                } else if (skelimport.cancelAllFlag) {
                    //Delete all the created files.
                    for (TFile tempFile : createdFiles) {
                        try {
                            tempFile.rm();
                        } catch (IOException e) {
                            LOGGER.warn(String.format("Unable to delete file, \"%s\".  Will retry on application exit.",
                                    tempFile.getAbsolutePath()));
                            tempFile.deleteOnExit();

                        }
                    }
                    //All the files are deleted.  Now remove the directories if we can.
                    purgeDirectoryStructure(new TFile(targetDir), true);
                    return 2;
                }
            } //end of for loop on onlyTargetFiles vector
        } finally {
            ConversionContext.exit();
        }
        String text = "";
        if (total >= 1) {
            StringBuilder buffer = new StringBuilder();
            for (int i = 0; i < total; i++) {
                buffer.append(createdFiles.get(i).getAbsolutePath());
                buffer.append("\n");
            }
            text = buffer.toString();
        } else {
            text = "No files created.";
        }
        String logFile = new TFile(MCREWConfig.getConfigDir(), "RUSLE2_Translation.log").getAbsolutePath();
        if (type == 0) {
            WepsMessageDialog.showScrollableMessage(source, total + " Skeleton Files Created", text, logFile,
                    WepsMessageDialog.OK_OPTION | WepsMessageDialog.SAVE_OPTION, JOptionPane.INFORMATION_MESSAGE);
        } else if (type == 1) {
            WepsMessageDialog.showScrollableMessage(source, total + " WEPS Management Files Created", text, logFile,
                    WepsMessageDialog.OK_OPTION | WepsMessageDialog.SAVE_OPTION, JOptionPane.INFORMATION_MESSAGE);
        } else {
            return 4;
        }
        logUnknownOperationsAndCrops(skelimport, null);

        return 1;
    } //end of method convertToManRec    

    /**
     * 
     * @param dir
     * @param first 
     */
    private void purgeDirectoryStructure(TFile dir, boolean first) {
        if (!dir.isDirectory()) {
            return;
        }
        for (java.io.File child : dir.listFiles()) {
            purgeDirectoryStructure(new TFile(child), false);
        }
        if (!first && dir.listFiles().length == 0) {
            try {
                dir.rm();
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }

    /**
     * 
     * @param skelimport
     * @param dir 
     */
    private void logUnknownOperationsAndCrops(SkelImportPanel skelimport, String dir) {
        //Check if we had any unknown crops or operations
        if (skelimport.hadUnknownCrop() || skelimport.hadUnknownOperation()) {
            try {
                //write to the project directory.
                if (dir == null) {
                    //Use the project directory
                    dir = "mcrew_cfg";
                }
                TFile translationFile = new TFile(MCREWConfig.getSkelTranslationPath());
                TFile file = new TFile(translationFile.getParentFile(), MCREWConfig.sDefaultSKEL_LOG);
                //Set to true so we append to the log.
                TFileWriter fw = new TFileWriter(file, true);
                try (BufferedWriter out = new BufferedWriter(fw)) {
                    out.write("#SKEL Conversion: " + new Date().toString());
                    out.newLine();
                    out.write("[Unkown Operations]");
                    out.newLine();
                    String spacer = " ";
                    Enumeration<String> enumOperations = skelimport.getUnknownOperations().elements();
                    while (enumOperations.hasMoreElements()) {
                        out.write(spacer + enumOperations.nextElement());
                        out.newLine();
                    }

                    out.write("[Unkown Crops]");
                    out.newLine();
                    Enumeration<String> enumCrops = skelimport.getUnknownCrops().elements();
                    while (enumCrops.hasMoreElements()) {
                        out.write(spacer + enumCrops.nextElement());
                        out.newLine();
                    }
                    out.write("#End of SKEL Conversion");
                    out.newLine();
                    out.newLine();
                }
                System.out.println("Wrote SKEL log to " + file.getCanonicalFile());
            } catch (IOException e) {
                System.err.println("There was an error writing the skel ops/crop log.");
            }
        }
    }
    
    
    /**
     * Check if source really could be a WEPS Management file.
     */
    private boolean isManFile(String fileName) {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new TFileReader(new TFile(fileName)));
            String temp;

            temp = br.readLine();

            if (temp != null) {
                if (temp.toUpperCase().contains("VERSION:")) {
                    return true;
                }
            }
        } catch (IOException e) {
            System.err.println("isManFile: " + e);
        } finally {
            try {
                br.close();
            } catch (IOException e) {
                LOGGER.error("Error closing management file stream.", e);
            }
        }

        return false;
    }
    
    /**
     *
     * @param <E>
     */
    public static class ConversionTask<E> {

        private final E from;
        private E to;

        /**
         *
         * @param from
         * @param to
         */
        public ConversionTask(E from, E to) {
            this.from = from;
            this.to = to;
        }

        /**
         *
         * @return
         */
        public E getFrom() {
            return from;
        }

        /**
         *
         * @return
         */
        public E getTo() {
            return to;
        }
    }

    /**
     *
     */
    public static class ConversionContext extends Context {

        private static final long serialVersionUID = 1L;

        Stack<ConversionTask<TFile>> stack;
        ConversionTask<TFile> task;

        /**
         *
         */
        @Override
        protected void enterAction() {

        }

        /**
         *
         */
        @Override
        protected void exitAction() {

        }

        /**
         *
         * @param stack
         */
        public static void enter(Stack<ConversionTask<TFile>> stack) {
            if (stack == null) {
                throw new IllegalStateException();
            }
            Context.enter(ConversionContext.class);

            getCurrent().stack = stack;
        }

        /**
         *
         */
        public static void exit() {
            Context.exit(ConversionContext.class);
        }

        /**
         *
         * @return
         */
        public static ConversionContext getCurrent() {
            for (Context ctx = Context.getCurrent(); ctx != null; ctx = ctx.getOuter()) {
                if (ctx instanceof ConversionContext) {
                    return (ConversionContext) ctx;
                }
            }
            return null;
        }

        /**
         *
         * @return
         */
        public static Stack<ConversionTask<TFile>> getStack() {
            ConversionContext current = getCurrent();
            return current != null ? current.stack : null;
        }

        /**
         *
         * @return
         */
        public static ConversionTask<TFile> getTask() {
            ConversionContext current = getCurrent();
            return current != null ? current.task : null;
        }
    }
    
    
    // Filter for selection skeleton XML files
    static class XMLSkelFilter extends javax.swing.filechooser.FileFilter {

        String fext;
        String fdescription;

        XMLSkelFilter(String exttext, String desc) {
            fext = exttext;
            fdescription = desc;
        }

        //Accept all directories and all XML/SKEL files.
        @Override
        public boolean accept(java.io.File f) {
            if (f.isDirectory()) {
                return true;
            }
            String ext = null;
            String s = f.getName();
            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(fext)) {
                    return true;
                } else {
                    return false;
                }
            }

            return false;
        }

        // The description of source filter
        @Override
        public String getDescription() {
            return fdescription;
        }
    }
}
