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

import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileInputStream;
import de.schlichtherle.truezip.file.TFileReader;
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import javax.swing.*;

import javax.help.*;
import java.util.*;
import org.openide.util.Exceptions;

import usda.weru.weps.*;
import usda.weru.util.*;

/**
 * The Debugging Reports report screen provides a means of directly accessing
 * all output files generated by the WEPS science model including those that are
 * used by the WEPS user interface reports. A list of selectable output files
 * are available on the dropdown list labeled "Select file to display". These
 * files are generally for advanced users and model developers.
 */
public class OutputViewer extends usda.weru.weps.reports.gui.OutputViewer_n {

    private static final long serialVersionUID = 1L;

    static final int MIN_WIDTH = 591;
    static final int MIN_HEIGHT = 590;

    String runDirectory = "";

    /**
     * Default constructor That builds the GUI and allow the access of output
     * data/files to check if any errors or mistakes have taken place during
     * executiom.
     */
    public OutputViewer() {
        super();
        //Setting the Icon Image in the title bar

        setIconImage(About.getWeruIconImage());
        addCSH();

    }

    /**
     * Single argument constructor That builds the GUI and allow the access of
     * output data/files to check if any errors or mistakes have taken place
     * during executiom.
     *
     * @param sTitle The string title for the GUI
     */
    public OutputViewer(String sTitle) {
        this();
        setTitle(sTitle);
        //Setting the Icon Image in the title bar

        super.setIconImage(About.getWeruIconImage());

    }

    /**
     * Two argument constructor That builds the GUI and allow the access of
     * output data/files to check if any errors or mistakes have taken place
     * during executiom.
     *
     * @param sTitle The string title for the GUI
     * @param inpfil The input file that store all the output data for viewing
     * in the viewer report screens.
     */
    public OutputViewer(String sTitle, TFile inpfil) {
        this();
        setTitle(sTitle);
        //Setting the Icon Image in the title bar

        super.setIconImage(About.getWeruIconImage());

        try {
            BufferedReader in = new BufferedReader(new TFileReader(inpfil));
            String temp;
            while ((temp = in.readLine()) != null) {
                JTA_text.append(temp + "\n");
            }
            JTA_text.moveCaretPosition(0);
            in.close();
        } catch (IOException e) {
            //System.err.println("RunFileData: " + e);
        }

    }

    /**
     * Four argument constructor That builds the GUI and allow the access of
     * output data/files to check if any errors or mistakes have taken place
     * during executiom.
     *
     * @param sTitle The string title for the GUI
     * @param runDir The directory where all the simulation RUN files for the
     * current project reside.r
     */
    public OutputViewer(String sTitle, String runDir) {
        this();
        this.setTitle(sTitle + " - " + runDir.substring(runDir.lastIndexOf(TFile.separatorChar) + 1));
        //Setting the Icon Image in the title bar
        ImageIcon weruFaceImg = null;
        weruFaceImg = new ImageIcon("./images/weruface.gif");
        super.setIconImage(weruFaceImg.getImage());
        HelpSet hs = Help.getHelpSet();
        HelpBroker hb = hs.createHelpBroker();
        Util.loadToolTips((Container) this, new TFile("cfg", "reportstooltips.cfg"));
        if (hb != null) {
            hb.enableHelpOnButton(JB_help, "outputDebugRepScreen_html", hs);
            ActionListener aboutHelp = new CSH.DisplayHelpFromSource(hb);
            JB_help.addActionListener(aboutHelp);
            JB_CSH.addActionListener(new CSH.DisplayHelpAfterTracking(hs, "javax.help.Popup", null));
            addCSH();
        } else {
            JB_CSH.setEnabled(false);
        }

        runDirectory = (runDir);
        TFile runDirFile = new TFile(runDir);
        String[] fileNames = runDirFile.list();
        Arrays.sort(fileNames);
        JCB_fileNames.setModel(new DefaultComboBoxModel<String>(fileNames));
//		for (int idx = 0; idx < fileNames.length; idx++) {
//			JCB_fileNames.addItem(fileNames[idx]);
//		}
//        JCB_fileNames.addItem(RunFileData.WepsData);

//		JCB_fileNames.setSelectedItem(RunFileData.HCOutputFileName);
        TFile tstFile = new TFile(runDir, RunFileData.WepsOutput);
        if (tstFile.exists() && tstFile.length() > 0) {
            JCB_fileNames.setSelectedItem(RunFileData.WepsOutput);
        } else {
            JCB_fileNames.setSelectedItem(RunFileData.StdErr);
        }
        JTA_text.setCaretPosition(0);
        JTA_text.moveCaretPosition(0);
    }

    /**
     * help stuff
     */
    private void addCSH() {
        CSH.setHelpIDString(JLabel1, "outputDebugRepScreen_html");
        CSH.setHelpIDString(JCB_fileNames, "outputDebugRepScreen_html");
        CSH.setHelpIDString(JB_OK, "outDebCloseButton_html");
        CSH.setHelpIDString(JB_print, "outDebPrintButton_html");
        //   CSH.setHelpIDString(JB_help, "outDebHelpButton_html");
        CSH.setHelpIDString(JB_CSH, "outDebCSHelpButton_html");
        CSH.setHelpIDString(JP_toolbar, "outDebButtons_html");
        CSH.setHelpIDString(JTB_main, "outDebButtons_html");
    }

    static void testMem() {
        //System.err.println("OP_m: memavail 1 " + Runtime.getRuntime().freeMemory() + " " +
//                Runtime.getRuntime().totalMemory());
        Runtime.getRuntime().runFinalization();
        Runtime.getRuntime().gc();
        //System.err.println("OP_m: memavail 2 " + Runtime.getRuntime().freeMemory() + " " +
        //              Runtime.getRuntime().totalMemory());
    }

    /**
     * Entry point for testing standalone. Used if this dialog is rum as an
     * independent application. If executed, makes the GUI for output viewer
     * panel visible.
     *
     * @param args These are the command line arguments passed to the main
     * method.
     */
    static public void main(String args[]) {
        String runDir = "";
        de.schlichtherle.truezip.file.TFile sf = null;
        testMem();
        RunFileData rfd = new RunFileData();
        WepsFileChooser wfc;
        //This object is used to set the Icon image in the Weps FileChooser dialog
        OutputViewer objectforIcon = new OutputViewer();
        if (args.length == 0 || !args[0].endsWith(RunFileData.RunSuffix)) {

            if (args.length == 0) {
                wfc = new WepsFileChooser(WepsFileChooser.Filetype.RUN, ".",
                        WepsFileChooser.SELECT);
                wfc.setCurrentDirectory(new de.schlichtherle.truezip.file.TFile("."));
            } else {
                wfc = new WepsFileChooser(WepsFileChooser.Filetype.RUN, args[0],
                        WepsFileChooser.SELECT);
                wfc.setCurrentDirectory(new de.schlichtherle.truezip.file.TFile(args[0]));
            }
            if (wfc.showDialog(objectforIcon) == JFileChooser.APPROVE_OPTION) {
                sf = new TFile(wfc.getSelectedFile());
                try {
                    runDir = sf.getCanonicalPath();
                } catch (java.io.IOException e) {//System.err.println(
                    //"Error getting canoncial path of runDir");
                }
                rfd.readRunFile(runDir);
                rfd.showRunFileData("this is a test");
            } else {
                //System.err.println("No project directory selected");
                return;
            }
        } else {
            runDir = args[0];
            if ((new TFile(runDir)).exists()) {
                rfd.readRunFile(runDir);
            } else {
                //System.err.println("CS_m : current run does not exist " + runDir);
                return;
            }
        }
        OutputViewer op = new OutputViewer("test", runDir);
        op.setVisible(true);
    }

    /**
     * Output viewer's display report will be shown when this method is invoked
     * from within or outside of the object.
     *
     * @param runDir The directory where all the simulation RUN files for the
     * current project reside.
     * @return
     */
    static public OutputViewer displayReport(String runDir) {
        de.schlichtherle.truezip.file.TFile sf = null;
        RunFileData rfd = new RunFileData();
        //This object is used to set the Icon image in the Weps FileChooser dialog
        OutputViewer objectforIcon = new OutputViewer();
        if (!runDir.endsWith(RunFileData.RunSuffix)) {
            WepsFileChooser wfc = new WepsFileChooser(WepsFileChooser.Filetype.RUN, runDir,
                    WepsFileChooser.SELECT);
            wfc.setCurrentDirectory(new de.schlichtherle.truezip.file.TFile(runDir));
            if (wfc.showDialog(objectforIcon) == JFileChooser.APPROVE_OPTION) {
                sf = new TFile(wfc.getSelectedFile());
                try {
                    runDir = sf.getCanonicalPath();
                } catch (java.io.IOException e) {//System.err.println(
                    //"Error getting canoncial path of runDir");
                }
                rfd.readRunFile(runDir);
                rfd.showRunFileData("this is a test");
            } else {
                //System.err.println("No project directory selected");
                return null;
            }
        } else if ((new TFile(runDir)).exists()) {
            rfd.readRunFile(runDir);
        } else {
            //System.err.println("CS_m : current run does not exist " + runDir);
            return null;
        }

        OutputViewer op = new OutputViewer("Science Model Reports", runDir);
        op.setVisible(true);
        return op;

    }

    /**
     * Any changes if made into the dialog will be accepted if this button is
     * invoked or triggerred.
     *
     * @param event Recognizes if this button event is triggered from the GUI or
     * not.
     */
    @Override
    protected void JBOK_actionPerformed(java.awt.event.ActionEvent event) {
        this.dispose();
    }

    /**
     * The action button which if invoked will print the entire output viewer
     * report for the selected crop file.
     *
     * @param event Recognizes the keyboard button click or mouse click for
     * passing the event selection to this method invoking its functionality of
     * printing the report.
     */
    @Override
    protected void JBPrint_actionPerformed(java.awt.event.ActionEvent event) {
        PrintUtilities.printComponent(JTA_text);
    }

    void loadWepsData(String runFilePathName, JTextArea JTA_text) {
        ObjectInputStream objStream = null;
        TFile inpfil = new TFile((new TFile(runDirectory)).getParentFile(),
                RunFileData.WepsData);
        try {
            TFileInputStream outStream = new TFileInputStream(inpfil);
            objStream = new ObjectInputStream(outStream);
            Hashtable<String, String> ht = Caster.<Hashtable<String, String>>cast(objStream.readObject());
            Vector<String> e = new Vector<>(ht.keySet());
            Collections.sort(e);
            for (String key : e) {
                String outVal = key + " -> " + ht.get(key);

                JTA_text.append(outVal + "\n");
            }
            objStream.close();
        } catch (java.io.StreamCorruptedException h) {
            try {
                if (objStream != null) {
                    objStream.close();
                }
            } catch (IOException g) {
                //System.err.println("RFD_rC: can't close " + inpfil + " " + g);
                g.printStackTrace();
            }
        } catch (java.lang.ClassNotFoundException f) {
            try {
                objStream.close();
            } catch (IOException g) {
                //System.err.println("CD_rC: can't close " + RunFileData.WepsData + " " + g);
                g.printStackTrace();
            }
        } catch (IOException e) {
            //System.err.println("CD_rC: can't read " + RunFileData.WepsData + " " + e);
            e.printStackTrace();
        }
    }

    /**
     * Allows the selection of files to be pulled out for viewing purpose within
     * the WEPS viewer report GUI.
     *
     * @param event Change in selection of the items in the combo/choice box.
     */
    @SuppressWarnings("empty-statement")
    @Override
    protected void JCBFileNames_itemStateChanged(java.awt.event.ItemEvent event) {
        if (ItemEvent.SELECTED != event.getStateChange()) {
            return;
        }
        Thread t = new Thread("OutputViewer") {
            @Override
            public void run() {
                ProgressMonitor progress = null;
                TFile file = new TFile(runDirectory,
                        (String) JCB_fileNames.getSelectedItem());

                progress = new ProgressMonitor(null, "Loading file...", file.getName(), 0, (int) file.length());

                JTA_text.setText("");
                if (!file.exists()) {
                    //System.out.println("OV_FN_iSC: " + inpfil);
                    loadWepsData(runDirectory, JTA_text);
                } else if (file.getName().endsWith(".pdf")) {
                    JTA_text.setText("Please view pdf files with a pdf viewer.");
                    progress.close();
                } else if (file.isDirectory()) {
                    JTA_text.setText("This is a directory.");
                    progress.close();
                } else {
                    try {
                        try (BufferedReader in = new BufferedReader(new TFileReader(file))) {
                            String temp;
                            while ((temp = in.readLine()) != null) {
                                progress.setProgress(temp.length());
                                JTA_text.append(temp + "\n");
                            }
                            progress.close();
                        }
                        JTA_text.setCaretPosition(0);
                        JTA_text.moveCaretPosition(0);
                    } catch (IOException e) {
                        //System.err.println("RunFileData: " + e);
                    }
                }
            }
        };

//        t.run();      //TODO : check to see if this is correct
        t.start();
        try {
            t.join();
        } catch (InterruptedException ex) {
            Exceptions.printStackTrace(ex);
        }
    }

    /**
     * This method adjust the components in the output viewer's report so that
     * the adjoining commponents are spaced uniformly w.r.t each other when a
     * window or frame is resized.
     *
     * @param event The resize event that occurs on the window.
     */
    @Override
    protected void OutputViewerN_componentResized(java.awt.event.ComponentEvent event) {
        validate();
        Dimension size = event.getComponent().getSize();

        if (size.getHeight() < MIN_HEIGHT) {
            size.height = MIN_HEIGHT;
            //System.out.println("In HeightTrigger .. Width is :"+size.getWidth()+"Heoght is :"+ size.getHeight());
        }
        if (size.getWidth() < MIN_WIDTH) {
            //System.out.println("In WidthTrigger .. Width is :"+size.getWidth()+"Heoght is :"+ size.getHeight());
            size.width = MIN_WIDTH;
        }
        size.height -= 90;
        JP_main.setSize(size);
        size.height -= 70;
        size.width -= 30;
        JTA_text.setSize(size);
        JSP_text.setSize(size);
        validate();
        repaint();
    }

}
