/*
 A basic implementation of the JFrame class.
 */
package usda.weru.erosion;

import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.swing.TFileChooser;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ItemEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import javax.help.HelpBroker;
import javax.help.HelpSet;
import javax.help.HelpSetException;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import usda.weru.util.About;
import usda.weru.util.ConfigData;
import usda.weru.util.Util;
import usda.weru.util.wepsFileChooser2.WepsFileChooser2;
import usda.weru.util.wepsFileChooser2.WepsFileTypes2;

/**
 * This class build the configuration panel GUI that allows the user to initialize and
 * modify all settings needed for the WEPS application.
 * @author  manmohan
 */
public class ConfigPanel extends usda.weru.erosion.gui.ConfigPanel_n implements PropertyChangeListener {

    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = LogManager.getLogger(ConfigPanel.class);
    private JFrame parent = null;
    private HelpSet hs;
    private String exeCmd = "-i${input.file}";
    /**
     * Help broker object for the context sensitive and generic application level help from the UI screens.
     */
    public HelpBroker hb;

    /**
     * Default constructor for the Configuration Panel GUI object that helps the
     * user in setting various paths like executables, directories such as management,
     * soil, database, etc along with the miscellaneous factors like setting units,etc.
     */
    public ConfigPanel() {
        super();
        //Setting the Icon Image in the title bar
        setIconImage(About.getWeruIconImage());

        JP_main.setVisible(true);
        addHelp();
        addKeyListeners();

        applyParameterAccessControls(this);
        // Making the Text Fields and buttons for Wind and Climate Files hidden.
        // We can remove these entirely once made sure that we dont use these anywhere else.
    }

    /**
     * Single argument constructor for the Configuration Panel GUI object that helps the
     * user in setting various paths like executables, directories such as management,
     * soil, database, etc along with the miscellaneous factors like setting units,etc.
     * The string passed to the constructor sets the title of the configuration panel.
     * @param parent The parent object in which the GUI resides .. i: the container
     * that holds the GUI.
     */
    public ConfigPanel(JFrame parent) {
        this();
        this.parent = parent;

    }

    /**
     * Single argument constructor for the Configuration Panel GUI object that helps the
     * user in setting various paths like executables, directories such as management,
     * soil, database, etc along with the miscellaneous factors like setting units,etc.
     * The string passed to the constructor sets the title of the configuration panel.
     * @param sTitle The title string for the parent frame of the GUI.
     */
    public ConfigPanel(String sTitle) {
        this();
        setTitle(sTitle);
    }

    /**
     *
     * @param component
     */
    public void applyParameterAccessControls(Component component) {
        if (component instanceof Container) {
            Container container = (Container) component;
            for (Component c : container.getComponents()) {
                applyParameterAccessControls(c);
            }
        }

        if (!this.equals(component)) {
            String name = component.getName();
            if (name == null) {
                return;
            }
            int index = name.indexOf(":");
            if (index > 0) {
                name = name.substring(0, index);
            }
            ConfigData.AccessLevel level = parseLevel(name);

            switch (level) {
                case Write:
                    component.setVisible(true);
                    component.setEnabled(true);
                    break;
                case Read:
                    component.setVisible(true);
                    component.setEnabled(false);
                    break;
                case Hidden:
                    component.setVisible(false);
                    component.setEnabled(false);
                    break;
                default:
            }
        }
    }

    private ConfigData.AccessLevel parseLevel(String name) {
        if (name == null) {
            return null;
        }
        ConfigData.AccessLevel level = null;
        String[] names = name.split(";");
        for (String splitName : names) {
            ConfigData.AccessLevel test = ConfigData.getDefault().getAccessLevel(splitName);
            level = ConfigData.AccessLevel.higher(level, test);
        }

        return level;
    }

    /**
     * This method adds listeners to all the text fields that go on the various
     * tabs of this configuration panel's GUI which the user intends to use for
     * setting up the directory paths and initializing the application to make
     * it run right.
     */
    private void addKeyListeners() {
        SymKey sk = new SymKey();

        JTF_exe.addKeyListener(sk);
        JTF_cmd.addKeyListener(sk);

        JTF_soilDB.addKeyListener(sk);
        JTF_projDir.addKeyListener(sk);

        JTF_emailSender.addKeyListener(sk);
        JTF_emailWeps.addKeyListener(sk);
        JTF_emailBugs.addKeyListener(sk);

    }

    /**
     * This method adds data from the help file to the different labels, buttons,
     * text field, etc. as tooltip help or context sensitive help which is to make the
     * end user understand its functionality and usability.
     */
    private void addHelp() {

        String jarFilePath = "jar/WepsHelp.jar";
        String dirFilePath = "help/MasterWeps.hs";
        TFile file_jar = new TFile(jarFilePath);
        TFile file_dir = new TFile(dirFilePath);
        if (file_jar.exists()) {
            //System.out.println("weps:addHelp-jar file found");
            jarHelp(jarFilePath);
        } else if (file_dir.exists()) {
            //System.out.println("weps:addhelp-dir help file found");
            dirHelp(dirFilePath);
        } else {
            //System.out.println("weps:addHelp-There are no help files");
            return;
        }

    } //end of addhelp()

    /**
     * This method gets the directory help system for the referenced GUI object.
     * @param dirFilePath The system directory path string for getting the help
     * system in running.
     */
    private void dirHelp(String dirFilePath) {
        try {
            URL hsURL = new URL((new TFile(".")).toURI().toURL(), dirFilePath);
            try {
                hs = new HelpSet(null, hsURL);
                //System.out.println("Found help set at " + hsURL);
            } catch (HelpSetException ex) {
                LOGGER.log(org.apache.logging.log4j.Level.ERROR, ex.getMessage());
                return;
            }
            //System.out.println("Found help set at " + hsURL);
        } catch (MalformedURLException ex) {
                LOGGER.log(org.apache.logging.log4j.Level.ERROR, ex.getMessage());
            return;
        }
        //new CSH.DisplayHelpFromSource(getHelpBroker()));
        addCSH(hs);

    } //end of dirHelp

    /**
     * This method adds data for the context sensitive help provided on these panels
     * by creating a helpbroker to assist itself in linking the appropriate .html pages
     * by making it by making it accessible on user's request to understand all about
     * itself.
     * @param hs The help system/set object necessary to be provided for creating
     * the help broker for the application to be able to provide the context sensitive
     * help on each component sitting on the GUI.
     */
    private void addCSH(HelpSet hs) {
        /*		hb = hs.createHelpBroker();
         //hb = hs.getHelpBroker();
         hb.enableHelpKey(getRootPane(), "mnuConfiguration_html", hs);
         ActionListener helper = new CSH.DisplayHelpFromSource(hb);
         ////System.out.println("I am in the WEPS addHelp()" + helper);
         JB_Help.addActionListener(helper);
         //If in future required for Context Sensitive Help
         // helpButton.addActionListener(new CSH.DisplayHelpAfterTracking(hs,"javax.help.Popup",null));
         //for all labels/fields in the Executables tab
         CSH.setHelpIDString(JLabel1, "execWinGenExe_html");
         CSH.setHelpIDString(JTF_winExe, "execWinGenExe_html");
         CSH.setHelpIDString(JLabel2, "execWinGenCmd_html");
         CSH.setHelpIDString(JTF_winCmd, "execWinGenCmd_html");
         CSH.setHelpIDString(JLabel3, "execCliGenExe_html");
         CSH.setHelpIDString(JTF_cliExe, "execCliGenExe_html");
         CSH.setHelpIDString(JLabel4, "execCliGenCmd_html");
         CSH.setHelpIDString(JTF_cliCmd, "execCliGenCmd_html");
         CSH.setHelpIDString(JLabel5, "execWepsExe_html");
         CSH.setHelpIDString(JTF_wepsExe, "execWepsExe_html");
         CSH.setHelpIDString(JLabel6, "execWepsCmd_html");
         //Text field and label for Weps calibration Cmd
         CSH.setHelpIDString(JTF_wepsCmd, "execWepsCmd_html");
         CSH.setHelpIDString(JL_calWepsCmd, "execWepsCalCmd_html");
        
         CSH.setHelpIDString(JTF_calWepsCmd, "execWepsCalCmd_html");
         CSH.setHelpIDString(JP_Exes, "execTab_html");
        
         // for all labels/fields in the Directories tab
         CSH.setHelpIDString(JLabel7, "dirManTemp_html");
         CSH.setHelpIDString(JTF_manTemp, "dirManTemp_html");
         CSH.setHelpIDString(JLabel8, "dirManSkel_html");
         CSH.setHelpIDString(JTF_manSkel, "dirManSkel_html");
         CSH.setHelpIDString(JLabel9, "dirManOperDB_html");
         CSH.setHelpIDString(JTF_manOperDB, "dirManOperDB_html");
         CSH.setHelpIDString(JLabel10, "dirCropDB_html");
         CSH.setHelpIDString(JTF_cropDB, "dirCropDB_html");
         CSH.setHelpIDString(JLabel34, "dirMCREWDir_html");
         CSH.setHelpIDString(JTF_MCREW, "dirMCREWDir_html");
         CSH.setHelpIDString(JLabel11, "dirSoilDB_html");
         CSH.setHelpIDString(JTF_soilDB, "dirSoilDB_html");
         //For the label and text field of Soil DB Spec.
         CSH.setHelpIDString(JLabel38, "dirSoilDBSpec_html");
         CSH.setHelpIDString(JTF_soilDBSpec, "dirSoilDBSpec_html");
        
         CSH.setHelpIDString(JLabel12, "dirProjDir_html");
         CSH.setHelpIDString(JTF_projDir, "dirProjDir_html");
        
         //For the label and text field of Mcrew Config
         CSH.setHelpIDString(JL_mcrewConfig, "dirMCREWconfig_html");
         CSH.setHelpIDString(JTF_mcrewConfig, "dirMCREWconfig_html");
        
         CSH.setHelpIDString(JP_Directories, "dirTab_html");
        
         //for all labels/fields in the Miscellaneous tab
         CSH.setHelpIDString(JLabel27, "miscUnits_html");
        
         CSH.setHelpIDString(JLabel28, "miscSearchRadius_html");
         CSH.setHelpIDString(JLabel32, "miscWindRadius_html");
         CSH.setHelpIDString(JTF_windRadius, "miscWindRadius_html");
         CSH.setHelpIDString(JLabel33, "miscCliRadius_html");
         CSH.setHelpIDString(JTF_cliRadius, "miscCliRadius_html");
         CSH.setHelpIDString(JLabel35, "miscTTDelay_html");
         //For the label and text field of Initial tool tip delay
         CSH.setHelpIDString(JLabel36, "miscTTInit_html");
         CSH.setHelpIDString(JTF_ttInit, "miscTTInit_html");
         //For the label and text field of Dismiss of tool tip delay
         CSH.setHelpIDString(JLabel37, "miscTTDismiss_html");
         CSH.setHelpIDString(JTF_ttDismiss, "miscTTDismiss_html");
        
         CSH.setHelpIDString(JXB_latLon, "miscLatLon_html");
         CSH.setHelpIDString(JXB_stateCounty, "miscStateCounty_html");
         CSH.setHelpIDString(JXB_elevation, "miscElevation_html");
         CSH.setHelpIDString(JXB_map, "miscMapButton_html");
         CSH.setHelpIDString(JXB_McrewEdit, "miscMCREWedit_html");
         CSH.setHelpIDString(JRB_english, "miscUnits_html");
         CSH.setHelpIDString(JRB_metric, "miscUnits_html");
         CSH.setHelpIDString(JLabel31, "miscTimeSteps_html");
         CSH.setHelpIDString(JTF_timeSteps, "miscTimeSteps_html");
         CSH.setHelpIDString(JP_Misc, "miscTab_html");
        
         //for all labels/fields in the Output tab
         CSH.setHelpIDString(JLabel17, "outReportPeriod_html");
         CSH.setHelpIDString(JRB_1, "outReportPeriod_html");
         CSH.setHelpIDString(JRB_2, "outReportPeriod_html");
         CSH.setHelpIDString(JRB_3, "outReportPeriod_html");
         CSH.setHelpIDString(JRB_4, "outReportPeriod_html");
         CSH.setHelpIDString(JLabel18, "outSubmodelReports_html");
         CSH.setHelpIDString(JLabel19, "outSubmodelReports_html");
         *//*
         CSH.setHelpIDString(JLabel20, "outSubmodelReports");
         CSH.setHelpIDString(JCB_hydro, "outSubHydrology");
         CSH.setHelpIDString(JCB_soil, "outSubSoil");
         CSH.setHelpIDString(JCB_man, "outSubMan");
         CSH.setHelpIDString(JCB_crop, "outSubCrop");
         CSH.setHelpIDString(JCB_dec, "outSubDec");
         CSH.setHelpIDString(JCB_ero, "outSubEro_html");
         */
        /*        CSH.setHelpIDString(JLabel21, "outSubHydrology_html");
         CSH.setHelpIDString(JTF_detHydro, "outSubHydrology_html");
         CSH.setHelpIDString(JLabel22, "outSubSoil_html");
         CSH.setHelpIDString(JTF_detSoil, "outSubSoil_html");
         CSH.setHelpIDString(JLabel23, "outSubMan_html");
         CSH.setHelpIDString(JTF_detMan, "outSubMan_html");
         CSH.setHelpIDString(JLabel24, "outSubCrop_html");
         CSH.setHelpIDString(JTF_detCrop, "outSubCrop_html");
         CSH.setHelpIDString(JLabel25, "outSubDec_html");
         CSH.setHelpIDString(JTF_detDec, "outSubDec_html");
         CSH.setHelpIDString(JLabel26, "outSubEro_html");
         CSH.setHelpIDString(JTF_detEro, "outSubEro_html");
         CSH.setHelpIDString(JP_Output, "outTab_html");
        
         //for all labels/fields in the Email tab
         CSH.setHelpIDString(JLabel13, "emlEmailSender_html");
         CSH.setHelpIDString(JTF_emailSender, "emlEmailSender_html");
         CSH.setHelpIDString(JLabel14, "emlEmailHost_html");
         CSH.setHelpIDString(JTF_emailHost, "emlEmailHost_html");
         CSH.setHelpIDString(JLabel15, "emlEmailComments_html");
         CSH.setHelpIDString(JTF_emailWeps, "emlEmailComments_html");
         CSH.setHelpIDString(JLabel16, "emlEmailBugs_html");
         CSH.setHelpIDString(JTF_emailBugs, "emlEmailBugs_html");
         CSH.setHelpIDString(JP_Email, "emlTab_html");
        
         //for all labels/fields in the Run tab
         CSH.setHelpIDString(JLabel30, "runRunType_html");
         CSH.setHelpIDString(JRB_NRCS, "runRunType_html");
         CSH.setHelpIDString(JRB_dates, "runRunType_html");
         CSH.setHelpIDString(JRB_cycle, "runRunType_html");
         CSH.setHelpIDString(JL_runLength, "runRunType_html");
         CSH.setHelpIDString(JTF_runLength, "runRunType_html");
         CSH.setHelpIDString(JLabel29, "runAltWeather_html");
         CSH.setHelpIDString(JCB_wind, "runAltWeather_html");
         CSH.setHelpIDString(JCB_climate, "runAltWeather_html");
         CSH.setHelpIDString(JP_Run, "runTab_html");
         */

        //       CSH.setHelpIDString(JBGP_runType, "runRunType");
 /*       CSH.setHelpIDString(JTF_windFile, "runAltWeather");
         CSH.setHelpIDString(JB_windFile, "runAltWeather");
         CSH.setHelpIDString(JCB_climate, "runAltWeather");
         CSH.setHelpIDString(JTF_climateFile, "runAltWeather");
         CSH.setHelpIDString(JB_climateFile, "runAltWeather");
         CSH.setHelpIDString(JCB_subdaily, "runAltWeather");
         CSH.setHelpIDString(JTF_subdailyFile, "runAltWeather");
         CSH.setHelpIDString(JB_subdailyFile, "runAltWeather");
         */
    }//end of addCSH

    /**
     * This method provides the jarFile that the help system for this GUI could use.
     * @param jarFilePath The jar file system path that tells where the file resides.
     */
    private void jarHelp(String jarFilePath) {

        hs = getHelpSet(jarFilePath);
        if (hs != null) {
            addCSH(hs);
        } else {
            //System.out.println("Can't find the helpSet-file.");
            return;
        }

    } //end of jarHelp

    /**
     * Returns the helpset file which is included in the jar file
     * @param jarFilePath The jar file system path that tells where the file resides.
     * @return HelpSet The object that stores all the notes and tooltiptext strings
     * needed for the user help on the components descriptions.
     *
     */
    protected HelpSet getHelpSet(String jarFilePath) {

        HelpSet hs = null;

        String hsName = null;
        JarFile jar;
        try {
            jar = new JarFile(jarFilePath);
        } catch (IOException ex) {
                LOGGER.log(org.apache.logging.log4j.Level.ERROR, ex.getMessage());
            return null;
        }
        Enumeration<JarEntry> entries = jar.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            String entryName = entry.getName();
            if (entryName.endsWith(".hs")) {
                hsName = entryName;
                break;
            }
        }
        URL url[] = getURLs("file:" + jarFilePath);
        ClassLoader cl = new URLClassLoader(url);
        URL hsUrl = HelpSet.findHelpSet(cl, hsName);
        try {
            hs = new HelpSet(cl, hsUrl);
        } catch (HelpSetException ex) {
            LOGGER.log(org.apache.logging.log4j.Level.ERROR, ex.getMessage());
            return null;
        }

        return hs;
    }

    /**
     * This function generates a URL from a string and then puts
     * it into a URL array
     * @param The string that represents the resource location.
     * @return URL[] The array that stores the resource objects at the specified
     * location.
     */
    private URL[] getURLs(String spec) {
        Vector<URL> v = new Vector<>();
        try {
            URL url = new URL(spec);
            v.addElement(url);
        } catch (Exception ex) {
            //System.err.println("cannot create URL for "+spec);
        }
        URL back[] = new URL[v.size()];
        v.copyInto(back);
        return back;
    }

    /**
     * This actionPerformed method is responsible for recognizing the path that
     * leads the application to the WEPS executable that generates the various
     * reports that we see on the interface GUI needed as an input argument for
     * the WEPS application to run.
     * @param event This action event is generated when the EXE path string is entered into
     * the WEPS executable labeled (WEPS exe) text field in the Executables Tab.
     */
    public void JTFWepsExe_actionPerformed(java.awt.event.ActionEvent event) {
//		firePropertyChange(ConfigData.SWEEPExe, null, JTF_exe.getText());
    }

    /**
     * This actionPerformed method is invoked when the user clicks the button for
     * path string to select the WEPS exe file via the file chooser through the
     * Executables Tab to be inserted in the WEPS Exe text field.
     * @param evt This action event is generated when the file chooser button of WEPS
     * exe text field is clicked.
     */
    public void wepsexeButton_actionPerformed(java.awt.event.ActionEvent evt) {
//            openFileChooser(JTF_wepsExe, true, "Select a File", 1);
//            firePropertyChange(ConfigData.WepsExe, null, JTF_wepsExe.getText());
    }

    /**
     *
     * @param jtf
     * @param acceptAllFilter
     * @param title
     * @param fileType
     */
    public void openFileChooser(JTextField jtf, boolean acceptAllFilter, String title, int fileType) {
        String workingDirPath = System.getProperty("user.dir");
        String selectedPath = "";
        String path = jtf.getText();
        String homeDirPath = ".";

        //the home directory path for the Mcrew Data Config file chooser dialog
        //should be relative to Mcrew Directory - neha
        TFile pathDir = new TFile(path);
        TFile parentDir = new TFile(pathDir.getParentFile());
        if (pathDir.exists() && parentDir != null) {
            homeDirPath = parentDir.getAbsolutePath();
        }

        //If a directory is to be chosen in the file chooser, then change the
        //"File Name" prompt to "Directory Name", Otherwise keep it as "File Name"
        if (fileType == 0) {
            UIManager.put("FileChooser.fileNameLabelText", "Directory Name");
        } else {
            UIManager.put("FileChooser.fileNameLabelText", "File Name");
        }
        WepsFileChooser2 jpc = new WepsFileChooser2(WepsFileTypes2.Dir, homeDirPath,
                WepsFileChooser2.Action.Select);

        jpc.setCurrentDirectory(homeDirPath);
        jpc.setAcceptAllFileFilterUsed(acceptAllFilter);

        //set the title of the dialog according to the parameter title
        jpc.setDialogTitle(title);
        //set the tooltip of "home" button to "Home" instead of "Desktop"
        jpc.homeToolTip(jpc);
        //remove the NewFolder button
        jpc.disableNewFolder(jpc);

        if (jpc.showDialog(this.JP_main) == TFileChooser.APPROVE_OPTION) {
            // work with the picked item
            try {
                selectedPath = jpc.getSelectedFile().getCanonicalPath();
            } catch (java.io.IOException e) {
                //System.err.println("CP-SFap: " + e);
            }

            if (selectedPath.startsWith(workingDirPath)) {
                int len = workingDirPath.length();
                selectedPath = selectedPath.substring(len + 1); //remove the file separator
            }

            //Replace the file separator '\' with '/'
            selectedPath = selectedPath.replace('\\', '/');

            jtf.setText(selectedPath);
        }
    }

    void makeSoil() {
        //String spec = JTF_soilDBSpec.getText();
        String disp = JTF_soilDB.getText();
        String db = disp;
//        if (spec.trim().length() > 0) {
//            int idx = spec.indexOf("$!db");
//            if (idx > 0) {
//                db = spec.substring(0,idx) + disp + spec.substring(idx+4);
//            }
//        }
        firePropertyChange(ConfigData.SoilDB, null, db);
    }

    /**
     * The text field that indicates the Soil directory name/path where the database MDB file resides.
     * @param event This event is generated when the Soil database directory path is
     * inserted either by typing in the text field or by using the filechooser to select
     * the path for files directly. Any changes made to the text in this field are recorded/saved
     * once it looses it focus.
     */
    @Override
    public void JTFSoilDB_FocusLost(java.awt.event.FocusEvent event) {
        if (event.isTemporary()) {
            return;
        }
        firePropertyChange(ConfigData.SoilDBDisp, null, JTF_soilDB.getText());
        makeSoil();
    }

    /**
     * This text field indicates the path where the Soil database spec file resides.
     * @param event This event is generated when the Soil database directory path is
     * inserted either by typing in the text field or by using the filechooser to select
     * the path for files directly. Any changes made to the text in this field are recorded/saved
     * once it looses its focus.
     */
    public void JTFSoilDBSpec_focusLost(java.awt.event.FocusEvent event) {
        if (event.isTemporary()) {
            return;
            //firePropertyChange(ConfigData.SoilDBSpec, null, JTF_soilDBSpec.getText());
        }
        makeSoil();
    }

    /**
     * This text field indicates the path where the project specific files/folders resides.
     * @param event This event is generated when the Soil database directory path is
     * inserted either by typing in the text field or by using the filechooser to select
     * the path for files directly. Any changes made to the text in this field are recorded/saved
     * once it recieves the keyboard enter event/mouse click event.
     */
    @Override
    public void JTFProjDir_ActionPerformed(java.awt.event.ActionEvent event) {
        firePropertyChange(ConfigData.SWEEPWorkDir, null, JTF_projDir.getText());
    }

    /**
     * This text field indicates the path where the project specific files/folders resides.
     * @param event This event is generated when the Soil database directory path is
     * inserted either by typing in the text field or by using the filechooser to select
     * the path for files directly. Any changes made to the text in this field are recorded/saved
     * once it looses its focus.
     */
    @Override
    public void JTFProjDir_FocusLost(java.awt.event.FocusEvent event) {
        if (event.isTemporary()) {
            return;
        }
        firePropertyChange(ConfigData.SWEEPWorkDir, null, JTF_projDir.getText());
    }

    /**
     *
     * @param event
     */
    @Override
    public void JTFEmailSender_ActionPerformed(java.awt.event.ActionEvent event) {
        firePropertyChange(ConfigData.EmailSender, null,
                JTF_emailSender.getText());
    }

    /**
     * Takes the recipient's address which in this case is the WEPS support team
     * as the email program's argument to notify the email recipient who sent
     * him the email qnd what the email is about.
     * @param event Takes the string value modified/entered as the email recipient's
     * address and uses this string for sending the messages.
     */
    @Override
    public void JTFEmailWeps_ActionPerformed(java.awt.event.ActionEvent event) {
        firePropertyChange(ConfigData.CommentAddr, null,
                JTF_emailWeps.getText());
    }

    /**
     * Takes the recipient's address which in this case is the WEPS support team
     * as the email program's argument to notify the email recipient about the bugs
     * and program crashes that occur due to the corrupt data or unanticipated executions
     * sequences.
     * @param event Takes the string value modified/entered as the email recipient's
     * address and uses this string for sending the messages.
     */
    @Override
    public void JTFEmailBugs_ActionPerformed(java.awt.event.ActionEvent event) {
        firePropertyChange(ConfigData.BugsAddr, null,
                JTF_emailBugs.getText());
    }

    /**
     * Takes the sender's address for the email program's argument to notify
     * the email recipient who sent him the email.
     * @param event Takes the string value modified/entered as the email sender's
     * address and uses this string for identification of incoming messages.
     * The string gets saved and accepted once the text field loses it focus.
     */
    @Override
    public void JTFEmailSender_FocusLost(java.awt.event.FocusEvent event) {
        if (event.isTemporary()) {
            return;
        }
        firePropertyChange(ConfigData.EmailSender, null,
                JTF_emailSender.getText());
    }

    /**
     * Takes the recipient's address which in this case is the WEPS support team
     * as the email program's argument to notify the email recipient who sent
     * him the email qnd what the email is about.
     * @param event Takes the string value modified/entered as the email recipient's
     * address and uses this string for sending the messages. The method gets
     * triggered when the cursor moves to a different component.
     */
    @Override
    public void JTFEmailWeps_FocusLost(java.awt.event.FocusEvent event) {
        if (event.isTemporary()) {
            return;
        }
        firePropertyChange(ConfigData.CommentAddr, null,
                JTF_emailWeps.getText());
    }

    /**
     * Takes the recipient's address which in this case is the WEPS support team
     * as the email program's argument to notify the email recipient about the bugs
     * and program crashes that occur due to the corrupt data or unanticipated executions
     * sequences.
     * @param event Takes the string value modified/entered as the email recipient's
     * address and uses this string for sending the messages. The method gets
     * triggered when the cursor moves to a different component.
     */
    @Override
    public void JTFEmailBugs_FocusLost(java.awt.event.FocusEvent event) {
        if (event.isTemporary()) {
            return;
        }
        firePropertyChange(ConfigData.BugsAddr, null,
                JTF_emailBugs.getText());
    }

    /**
     * The mode in which we run the application for data representation and
     * retrival.
     * @param event Mouse click/keyboard event that selects/deselects the option
     * for deciding which mode the application needs to be executed for data
     * presentation.
     */
    @Override
    public void JBOK_ActionPerformed(java.awt.event.ActionEvent event) {
        this.setVisible(false);
        invalidate();
        repaint();

        parent.invalidate();
        parent.repaint();

    }

    /**
     * This button accepts all changes made from initial saved state to current state
     * and saves that data for future retrieval.
     * @param event This button accepts all the modifications done to this data and various option selections
     * and allows the user to access this data again if needed in future.
     */
    @Override
    public void JBSave_ActionPerformed(java.awt.event.ActionEvent event) {
        ConfigData.getDefault().save();
    }

    /**
     * This button gets the GUI related help from java help provided in the application.
     * @param evt This button accepts the help request from any particular region of the GUI's components.
     */
    @Override
    public void JB_Help_ActionPerformed(java.awt.event.ActionEvent evt) {
        (new usda.weru.util.NotImplemented("Help")).setVisible(true);
    }

    /**
     * This method recognises the change in status or property of the components
     * in various containers that are registered to be tracked for any changes with
     * configuration panel and eventually react to those events.
     * @param evt
     */
    @Override
    protected void JTF_outputFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_JTF_outputFocusLost
        JTF_outputActionPerformed(null);
    }//GEN-LAST:event_JTF_outputFocusLost

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_outputActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_JTF_outputActionPerformed
        exeCmd = JTF_output.getText();
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JTF_outputActionPerformed
    private static String Eplt = " -Eplt";

    /**
     *
     * @param evt
     */
    @Override
    protected void JCB_plotItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_JCB_plotItemStateChanged
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            if (exeCmd.indexOf(Eplt) >= 0) {
                return;
            }
            exeCmd += Eplt;
        } else {
            exeCmd = exeCmd.replace(Eplt, "");
        }
        JTF_output.setText(exeCmd);
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JCB_plotItemStateChanged
    private static String Emit = " -Emit";

    /**
     *
     * @param evt
     */
    @Override
    protected void JCB_subdailyItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_JCB_subdailyItemStateChanged
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            if (exeCmd.indexOf(Emit) >= 0) {
                return;
            }
            exeCmd += Emit;
        } else {
            exeCmd = exeCmd.replace(Emit, "");
        }
        JTF_output.setText(exeCmd);
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JCB_subdailyItemStateChanged
    private static String Esgrd = " -Esgrd";

    /**
     *
     * @param evt
     */
    @Override
    protected void JCB_subdailyGridItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_JCB_subdailyItemStateChanged
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            if (exeCmd.indexOf(Esgrd) >= 0) {
                return;
            }
            exeCmd += Esgrd;
        } else {
            exeCmd = exeCmd.replace(Esgrd, "");
        }
        JTF_output.setText(exeCmd);
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JCB_subdailyItemStateChanged
    private static String Egrd = " -Egrd";

    /**
     *
     * @param evt
     */
    @Override
    protected void JCB_gridItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_JCB_gridItemStateChanged
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            if (exeCmd.indexOf(Egrd) >= 0) {
                return;
            }
            exeCmd += Egrd;
        } else {
            exeCmd = exeCmd.replace(Egrd, "");
        }
        JTF_output.setText(exeCmd);
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JCB_gridItemStateChanged
    private static String Erod = " -Erod";

    /**
     *
     * @param evt
     */
    @Override
    protected void JCB_summaryItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_JCB_summaryItemStateChanged
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            if (exeCmd.indexOf(Erod) >= 0) {
                return;
            }
            exeCmd += Erod;
        } else {
            exeCmd = exeCmd.replace(Erod, "");
        }
        JTF_output.setText(exeCmd);
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JCB_summaryItemStateChanged
    private static String Einp = " -Einp";

    /**
     *
     * @param evt
     */
    @Override
    protected void JCB_echoItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_JCB_echoItemStateChanged
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            if (exeCmd.indexOf(Einp) >= 0) {
                return;
            }
            exeCmd += Einp;
        } else {
            exeCmd = exeCmd.replace(Einp, "");
        }
        JTF_output.setText(exeCmd);
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JCB_echoItemStateChanged

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_yGridFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_JTF_yGridFocusLost
        JTF_yGridActionPerformed(null);
    }//GEN-LAST:event_JTF_yGridFocusLost
    private static String Uflg = "-u ";

    /**
     *
     * @param evt
     */
    @Override
    protected void JCB_surfaceUpdateItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_JCB_surfaceUpdateItemStateChanged
        if (evt.getStateChange() == ItemEvent.SELECTED) {
            if (exeCmd.indexOf(Uflg) >= 0) {
                return;
            }
            exeCmd = Uflg + exeCmd;
            exeCmd = exeCmd.replaceFirst("-t[0-9]+ ", "");
            JTF_surfaceUpdate.setText("");
        } else {
            exeCmd = exeCmd.replace(Uflg, "");
        }
        JTF_output.setText(exeCmd);
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JCB_surfaceUpdateItemStateChanged

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_yGridActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_JTF_yGridActionPerformed
        String textStr = JTF_yGrid.getText().trim();
        if (textStr.length() > 0) {
            if (exeCmd.indexOf("-y") >= 0) {
                exeCmd = exeCmd.replaceFirst("-y[0-9]+", "-y" + textStr.trim());
            } else {
                exeCmd = "-y" + textStr.trim() + " " + exeCmd;
            }
        } else {
            if (exeCmd.indexOf("-y") >= 0) {
                exeCmd = exeCmd.replaceFirst("-y[0-9]+ ", "");
                exeCmd = exeCmd.replaceFirst("-x[0-9]+ ", "");
                JTF_xGrid.setText("");
            } else {
            }
        }
        if (exeCmd.indexOf("-x") == -1 && exeCmd.indexOf("-y") >= 0) {
            exeCmd = "-x" + textStr + " " + exeCmd;
            JTF_xGrid.setText(textStr);
        }
        JTF_output.setText(exeCmd);
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JTF_yGridActionPerformed

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_xGridFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_JTF_xGridFocusLost
        JTF_xGridActionPerformed(null);
    }//GEN-LAST:event_JTF_xGridFocusLost

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_xGridActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_JTF_xGridActionPerformed
        String textStr = JTF_xGrid.getText().trim();
        if (textStr.length() > 0) {
            if (exeCmd.indexOf("-x") >= 0) {
                exeCmd = exeCmd.replaceFirst("-x[0-9]+", "-x" + textStr.trim());
            } else {
                exeCmd = "-x" + textStr.trim() + " " + exeCmd;
            }
        } else {
            if (exeCmd.indexOf("-x") >= 0) {
                exeCmd = exeCmd.replaceFirst("-x[0-9]+ ", "");
                exeCmd = exeCmd.replaceFirst("-y[0-9]+ ", "");
                JTF_yGrid.setText("");
            } else {
            }
        }
        if (exeCmd.indexOf("-x") >= 0 && exeCmd.indexOf("-y") == -1) {
            exeCmd = "-y" + textStr + " " + exeCmd;
            JTF_yGrid.setText(textStr);
        }
        JTF_output.setText(exeCmd);
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JTF_xGridActionPerformed

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_surfaceUpdateFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_JTF_surfaceUpdateFocusLost
        JTF_surfaceUpdateActionPerformed(null);
    }//GEN-LAST:event_JTF_surfaceUpdateFocusLost

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_surfaceUpdateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_JTF_surfaceUpdateActionPerformed
        String textStr = JTF_surfaceUpdate.getText().trim();
        if (textStr.length() > 0) {
            if (exeCmd.indexOf("-t") >= 0) {
                exeCmd = exeCmd.replaceFirst("-t[0-9]+", "-t" + textStr.trim());
            } else {
                exeCmd = "-t" + textStr.trim() + " " + exeCmd;
            }
        } else {
            if (exeCmd.indexOf("-t") >= 0) {
                exeCmd = exeCmd.replaceFirst("-t[0-9]+ ", "");
            } else {
            }
        }
        JTF_output.setText(exeCmd);
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JTF_surfaceUpdateActionPerformed

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_cmdFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_JTF_cmdFocusLost
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JTF_cmdFocusLost

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_cmdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_JTF_cmdActionPerformed
        firePropertyChange(ConfigData.SWEEPCmd, null, exeCmd);
    }//GEN-LAST:event_JTF_cmdActionPerformed

    private void handleFileButtonPressed(javax.swing.JTextField jtf,
            String uiManager1,
            String uiManager2,
            WepsFileTypes2 wfpType,
            String dialogTitle,
            String property) {

        String workingDirPath = System.getProperty("user.dir");
        String homeDirPath = workingDirPath;
        String selectedPath = "";
        String path = jtf.getText();
        path = Util.parse(path);
        TFile pathDir = new TFile(path).getCanOrAbsFile();
        if (pathDir.isFile()) {
            TFile parentDir = new TFile(pathDir.getParentFile());
            if (pathDir.exists() && parentDir != null) {
                homeDirPath = parentDir.getAbsolutePath();
            }
        }
        //Set the file prompt to "File Name", since the soil database file
        //is set as the default selection in the filechooser dialog
        UIManager.put(uiManager1, uiManager2);
        WepsFileChooser2 jpc = new WepsFileChooser2(wfpType, homeDirPath,
                WepsFileChooser2.Action.Select);
        jpc.setDialogTitle(dialogTitle);
        jpc.setCurrentDirectory(homeDirPath);
        //set the tooltip of "home" button to "Home" instead of "Desktop"
//			jpc.homeToolTip(jpc);
        //remove the NewFolder button
        jpc.disableNewFolder(jpc);

        if (jpc.showDialog(this.JP_main) == TFileChooser.APPROVE_OPTION) {
            // work with the picked item
            try {
                selectedPath = jpc.getSelectedFile().getCanonicalPath();
            } catch (java.io.IOException e) {
                //System.err.println("CP-SFap: " + e);
            }

            if (selectedPath.startsWith(workingDirPath)) {
                int len = workingDirPath.length();
                selectedPath = selectedPath.substring(len + 1); //remove the file separator
            }

            //Replace the file separator '\' with '/'
            selectedPath = selectedPath.replace('\\', '/');

//            jtf.setText(selectedPath);
//            firePropertyChange(property, null, jtf.getText());
            firePropertyChange(property, null, selectedPath);
        }
    }

    /**
     *
     * @param evt
     */
    @Override
    public void projectsDirButton_ActionPerformed(java.awt.event.ActionEvent evt) {

        handleFileButtonPressed(JTF_projDir,
                "FileChooser.fileNameLabelText",
                "Projects directory",
                WepsFileTypes2.Dir,
                "Select projects directory",
                ConfigData.SWEEPWorkDir);
//        openFileChooser(JTF_projDir, false, "Select a Directory", 0);
//        firePropertyChange(ConfigData.SWEEPWorkDir, null, JTF_projDir.getText());
    }

    /**
     *
     * @param evt
     */
    @Override
    public void soilDbButton_ActionPerformed(java.awt.event.ActionEvent evt) {

        handleFileButtonPressed(JTF_soilDB,
                "FileChooser.fileNameLabelText",
                "SSURGO db or Directory Name",
                WepsFileTypes2.SoilDB,
                "Select a SSURGO soil database file(.mdb) or directory",
                ConfigData.SoilDBDisp);
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void JB_exeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_JB_exeActionPerformed
        handleFileButtonPressed(JTF_exe,
                "FileChooser.fileNameLabelText",
                "SWEEP exe file name",
                WepsFileTypes2.Executable,
                "Select the exe file name",
                ConfigData.SWEEPExe);
    }//GEN-LAST:event_JB_exeActionPerformed

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_exeFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_JTF_exeFocusLost
        firePropertyChange(ConfigData.SWEEPExe, null, JTF_exe.getText());
    }//GEN-LAST:event_JTF_exeFocusLost

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_exeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_JTF_exeActionPerformed
        firePropertyChange(ConfigData.SWEEPExe, null, JTF_exe.getText());
    }//GEN-LAST:event_JTF_exeActionPerformed

    /**
     *
     * @param evt
     */
    @Override
    protected void JB_windDBActionPerformed(java.awt.event.ActionEvent evt) {
        handleFileButtonPressed(JTF_windDB,
                "FileChooser.fileNameLabelText",
                "Wind file db",
                WepsFileTypes2.WindDB,
                "Select the wind db file name",
                ConfigData.WinData);
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_windDBFocusLost(java.awt.event.FocusEvent evt) {
        JTF_windDBActionPerformed(null);
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_windDBActionPerformed(java.awt.event.ActionEvent evt) {
        firePropertyChange(ConfigData.WinData, null, JTF_windDB.getText());
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void JB_barriers_actionPerformed(java.awt.event.ActionEvent evt) {
        handleFileButtonPressed(JTF_barriers,
                "FileChooser.fileNameLabelText",
                "Barriers File",
                WepsFileTypes2.Dat,
                "Select the barriers file name",
                ConfigData.BarriersFile);
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_barriers_actionPerformed(java.awt.event.ActionEvent evt) {
        firePropertyChange(ConfigData.BarriersFile, null, JTF_barriers.getText());
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void JTF_barriers_focusLost(java.awt.event.FocusEvent evt) {
        firePropertyChange(ConfigData.BarriersFile, null, JTF_barriers.getText());
    }

    private void parseCmd(String cmdStr) {
        JTF_output.setText(cmdStr);
        JTF_cmd.setText(cmdStr);
        StringTokenizer st = new StringTokenizer(cmdStr);
        while (st.hasMoreTokens()) {
            String tok = st.nextToken();
            if (tok.equals("-Einp")) {
                JCB_echo.setSelected(true);
            } else if (tok.equals("-Egrd")) {
                JCB_grid.setSelected(true);
            } else if (tok.equals("-Emit")) {
                JCB_subdaily.setSelected(true);
            } else if (tok.equals("-Eplt")) {
                JCB_plot.setSelected(true);
            } else if (tok.equals("-Erod")) {
                JCB_summary.setSelected(true);
            } else if (tok.equals("-Esgrd")) {
                JCB_subdailyGrid.setSelected(true);
            } else if (tok.equals("-u")) {
                JCB_surfaceUpdate.setSelected(true);
            } else if (tok.startsWith("-t")) {
                JTF_surfaceUpdate.setText(tok.substring(2));
            } else if (tok.startsWith("-x")) {
                JTF_xGrid.setText(tok.substring(2));
            } else if (tok.startsWith("-y")) {
                JTF_yGrid.setText(tok.substring(2));
            }
        }
    }

    /**
     *
     * @param e
     */
    @Override
    public void propertyChange(PropertyChangeEvent e) {

        if (e.getPropertyName().equals(ConfigData.SWEEPExe)) {
            JTF_exe.setText((String) e.getNewValue());
        } else if (e.getPropertyName().equals(ConfigData.SWEEPCmd)) {
            exeCmd = (String) e.getNewValue();
            parseCmd(exeCmd);
        } else if (e.getPropertyName().equals(ConfigData.SoilDB)) {
            JTF_soilDB.setText((String) e.getNewValue());
        }
        else if (e.getPropertyName().equals(ConfigData.SWEEPWorkDir)) {
            JTF_projDir.setText((String) e.getNewValue());
        } else if (e.getPropertyName().equals(ConfigData.WinData)) {
            JTF_windDB.setText((String) e.getNewValue());
        } else if (e.getPropertyName().equals(ConfigData.EmailSender)) {
            JTF_emailSender.setText((String) e.getNewValue());
        } else if (e.getPropertyName().equals(ConfigData.CommentAddr)) {
            JTF_emailWeps.setText((String) e.getNewValue());
        } else if (e.getPropertyName().equals(ConfigData.BugsAddr)) {
            JTF_emailBugs.setText((String) e.getNewValue());
        } else if (e.getPropertyName().equals(ConfigData.BarriersFile)) {
            JTF_barriers.setText((String) e.getNewValue());
        }
    }

    static class SymKey extends java.awt.event.KeyAdapter {

        @Override
        public void keyTyped(java.awt.event.KeyEvent event) {
        }
    }
}
