/*
 * SoilChooser.java
 *
 * Created on April 18, 2007, 9:58 AM
 *
 */
package usda.weru.soil;

import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeSupport;
import de.schlichtherle.truezip.file.TFile;
import java.awt.EventQueue;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.ProgressMonitor;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.apache.log4j.Logger;
import usda.weru.soil.gui.SoilChooser_n;
import usda.weru.util.ConfigData;
import usda.weru.util.LazyLoadingTreeController;
import usda.weru.util.WepsMessage;
import usda.weru.util.WepsMessageDialog;
import usda.weru.util.WepsMessageLog;
import usda.weru.weps.RunFileData;

/**
 *
 * @author Joseph Levin
 */
public class SoilChooser extends SoilChooser_n {

    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = Logger.getLogger(SoilChooser.class);
    private TFile c_projectDirectory;
    private SoilTreeModel c_model;
    private PropertyChangeSupport c_changes;
    private Soil c_soil;
    private boolean useTempFile;

    /** Creates a new instance of SoilChooser */
    public SoilChooser() {
        init();
    }

    /**
     *
     * @param parent
     * @param projectDirectory
     * @param soilFile
     * @param changes
     */
    public SoilChooser(Frame parent, TFile projectDirectory, TFile soilFile, PropertyChangeSupport changes) {
        super(parent);
        LOGGER.debug("creating soil chooser");
        init();
        c_projectDirectory = projectDirectory;
        //setRootFile(soilFile);
        c_changes = changes;
        if (parent instanceof Soil) {
            c_soil = (Soil) parent;
        }
    }

    /**
     *
     * @param temp
     */
    public void setUseTempFile(boolean temp) {
        this.useTempFile = true;
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void formWindow_closed(java.awt.event.WindowEvent evt) {
    }

    private void init() {
        setModal(true);
        c_model = new InternalSoilTreeModel();
        g_tree.setModel(c_model);
        new LazyLoadingTreeController(g_tree);
        g_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        g_tree.expandPath(c_model.getPathToTemplates());
        g_tree.setRootVisible(false);
        setTitle("Select Soil");
    }

    /**
     * Makes the soil data mart folder the currently selected folder.
     * 
     * NOTE:  any change to the folders in the soil chooser will probably make this
     * need to change values.
     */
    public void setSelected()
    {
        g_tree.setSelectionRow(5);
    }
    
    /**
     *
     * @param dir
     */
    public void setProjectDirectory(TFile dir) {
        c_projectDirectory = dir;
    }

    /**
     *
     * @param changes
     */
    public void setChanges(PropertyChangeSupport changes) {
        c_changes = changes;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        JFileChooser jfc = new JFileChooser();
        jfc.setMultiSelectionEnabled(false);
        jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        final SoilChooser sc = new SoilChooser();
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                sc.setVisible(true);
            }
        });
        int result = jfc.showOpenDialog(sc);
        if (result == JFileChooser.APPROVE_OPTION) {
            //sc.setRootFile(file);
            sc.setProjectDirectory(new TFile("."));
        }

    }

    private boolean isSoil(Object o) {
        if (o instanceof TreeNode) {
            TreeNode node = (TreeNode) o;
            for (SoilDatabase database : c_model.getDatabases()) {
                if (database.isSoil(node)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void treeValueChanged(TreeSelectionEvent evt) {
        Object o = evt.getPath().getLastPathComponent();
        g_selectButton.setEnabled(isSoil(o));
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void treeMouseClicked(java.awt.event.MouseEvent evt) {
        if (evt.getClickCount() == 2) {
            loadSelectedNode();
        }
    }

    private void loadSelectedNode() {
        TreePath selectedPath = g_tree.getSelectionPath();
        if (selectedPath == null) {
            return;
        }
        Object o = selectedPath.getLastPathComponent();
        if (o instanceof TreeNode) {
            final TreeNode node = (TreeNode) o;
            for (final SoilDatabase database : c_model.getDatabases()) {
                if (database.isSoil(node)) {
                    //Thread off the loading of the soil ifc with a progress monitor.
                    final ProgressMonitor progress = new ProgressMonitor(this, "Loading Soil Record", "", 0, 100);
                    progress.setMillisToDecideToPopup(0);
                    progress.setMillisToPopup(0);
                    Thread task = new Thread("Selected Node Loader") {
                        @Override
                        public void run() {
                            setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR));
                            try {
                                IFC ifc = database.getIfcFromNode(node, progress);
                                if (ifc != null) {
                                    //WepsMessageLog log = new WepsMessageLog();
                                    WepsMessageLog log = ifc.getLog();

                                    if (log.getCount(WepsMessage.MessageSeverity.ERROR) == 0) {
                                        if (c_soil != null) {
                                            c_soil.ifcptr = ifc;
                                            c_soil.ifcptr.adjustIfc();
                                            c_soil.viewLayers(c_soil.ifcptr.getFileName());
                                            c_soil.setMenuEnable("Save", true);
                                            c_soil.setMenuEnable("Save As", true);
                                            c_soil.setMenuEnable("print", true);
                                        } else {
                                            // sends double errors to IFC file extracted from NASIS
                                            // ifc.sendErrorsToInternalVariable();
                                            if (useTempFile) {
                                                TFile temp = new TFile(TFile.createTempFile("soilchooser", ".ifc"));
                                                ifc.writeNewIfc(temp.getAbsolutePath(), c_changes);
                                                temp.deleteOnExit();
                                            } else {
                                                ifc.writeNewIfc(c_projectDirectory.getAbsolutePath(), c_changes);
                                            }
                                            c_changes.firePropertyChange(RunFileData.SoilRockFragments, null, "0.0");
                                            c_changes.firePropertyChange(RunFileData.AverageSlope, null, "-1");
                                        }
                                        //Ask the swing thread to hide the form
                                        SwingUtilities.invokeLater(new Runnable() {
                                            @Override
                                            public void run() {
                                                progress.close();
                                                //setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                                                setVisible(false);
                                            }
                                        });
                                    } else { //We have errors to report
                                        if (!NASIS.getEstimateNullValues() && log.getCount(WepsMessage.MessageSeverity.ERROR) > 0) {
                                            WepsMessageDialog.showMessageList(null,
                                                    "Soil Record", c_projectDirectory.getAbsolutePath(),
                                                    log.getMessages(WepsMessage.MessageSeverity.ERROR));
                                        } else {
                                            WepsMessageDialog.showMessageList(null, "Soil Record",
                                                    c_projectDirectory.getAbsolutePath(),
                                                    log.getMessages(WepsMessage.MessageSeverity.ERROR,
                                                            WepsMessage.MessageSeverity.WARNING));
                                        }

                                    }
                                }
                            } catch (OrganicSoilException ose) {
                                //the soil being loaded
                                String message = ose.getMessage();
                                final JOptionPane pane = new JOptionPane(
                                        "The selected soil is not supported by the WEPS science model."
                                        + "  The high organic content may cause unexpected results."
                                        + (message != null ? "\n" + message + "\n" : "\n")
                                        + "Do you want to use the supplied organic soil substitute?\n"
                                        + "Note that selecting \"No\" will revert the soil to the previously selected record.",
                                        JOptionPane.WARNING_MESSAGE, JOptionPane.YES_NO_OPTION) {

                                            private static final long serialVersionUID = 1L;

                                            @Override
                                            public int getMaxCharactersPerLineCount() {
                                                return 80;
                                            }

                                        };

                                final JDialog dialog = pane.createDialog(SoilChooser.this, "Organic Soil");
                                try {
                                    EventQueue.invokeAndWait(new Runnable() {

                                        @Override
                                        public void run() {
                                            dialog.setVisible(true);
                                            int result = pane.getValue() != null
                                                    ? Integer.valueOf(pane.getValue().toString()) : JOptionPane.CANCEL_OPTION;
                                            if (result == JOptionPane.YES_OPTION) {
                                                //use the organic soil, close soil chooser
                                                c_changes.firePropertyChange(RunFileData.SoilFile, null,
                                                        ConfigData.getDefault().getDataParsed(ConfigData.SoilOrganicFile));
                                                SoilChooser.this.setVisible(false);

                                            } else {
                                                //do nothing, the SoilChooser remains open
                                            }
                                        }

                                    });
                                } catch (InterruptedException | InvocationTargetException e) {
                                    LOGGER.error("Unexpected error while waiting for the edt "
                                            + "to return from the organic soil prompt.", e);
                                }
                            } catch (IOException | ArithmeticException e) {
                                //some error loading the soil record.
                                progress.close();
                                JOptionPane.showMessageDialog(SoilChooser.this, "Unknown error while loading a soil record.",
                                        "Loading Error", JOptionPane.ERROR_MESSAGE);

                            } finally {
                                progress.close();
                                setCursor(java.awt.Cursor.getDefaultCursor());
                            }

                        }
                    };
                    task.start();

                    //This database was able to provide the soil,                     
                    break;
                }
            }
        }
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void cancelButtonActionPerformed(ActionEvent evt) {
        setVisible(false);
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void selectButtonActionPerformed(ActionEvent evt) {
        loadSelectedNode();
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void indexActionPerformed(java.awt.event.ActionEvent evt) {
        //setRootFile(c_rootFile);
    }

    /**
     *
     * @param b
     */
    @Override
    public void setVisible(boolean b) {
        if (b) {
            LOGGER.debug("showing soil chooser");
        } else {
            LOGGER.debug("hiding soil chooser");
        }
        super.setVisible(b);
    }

    class InternalSoilTreeModel extends SoilTreeModel {

        private static final long serialVersionUID = 1L;

        public InternalSoilTreeModel() {
            super(true);
        }
    }

}
