/*
        A basic implementation of the JFrame class.
 */

package usda.weru.weps.reports;

import de.schlichtherle.io.File;
import de.schlichtherle.io.FileInputStream;
import de.schlichtherle.io.FileReader;
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 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 {
    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, File inpfil) {
        this();
        setTitle(sTitle);
        //Setting the Icon Image in the title bar

        super.setIconImage(About.getWeruIconImage());
        
        try {
            BufferedReader in = new BufferedReader(new FileReader(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
     * @param hb The help broker object used for accessing the JAVA help API for pulling the help
     * files on each component associated to this particular interface.
     * @param hs To provide context-sensitive help for a GUI component (that is, a component that is
     * sub-classed from the JComponent class), you must associate a help ID with that component. To make
     * that association, you set the helpID property and (if you use multiple HelpSets) the HelpSet in the JComponent.
     */
    public OutputViewer(String sTitle, String runDir) {
        this();
        this.setTitle(sTitle + " - " + runDir.substring(runDir.lastIndexOf(File.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 File("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);
        File runDirFile = new File(runDir);
        String[] fileNames = runDirFile.list();
        JCB_fileNames.setModel(new DefaultComboBoxModel(fileNames));
//		for (int idx = 0; idx < fileNames.length; idx++) {
//			JCB_fileNames.addItem(fileNames[idx]);
//		}
        JCB_fileNames.addItem(RunFileData.WepsData);
        
//		JCB_fileNames.setSelectedItem(RunFileData.HCOutputFileName);
        File tstFile = new File(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.io.File 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.RUN,".",
                        WepsFileChooser.SELECT);
                wfc.setCurrentDirectory(new de.schlichtherle.io.File("."));
            } else {
                wfc = new WepsFileChooser(WepsFileChooser.RUN,args[0],
                        WepsFileChooser.SELECT);
                wfc.setCurrentDirectory(new de.schlichtherle.io.File(args[0]));
            }
            if (wfc.showDialog(objectforIcon) == JFileChooser.APPROVE_OPTION) {
                sf = new File(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 File(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.
     * @param measurementUnits The units used for data representation in these screen.
     * @param hb The help broker object used for accessing the JAVA help API for pulling the help
     * files on each component associated to this particular interface.
     * @param hs To provide context-sensitive help for a GUI component (that is, a component that is
     * sub-classed from the JComponent class), you must associate a help ID with that component. To make
     * that association, you set the helpID property and (if you use multiple HelpSets) the HelpSet in the JComponent.
     */
    static public OutputViewer displayReport(String runDir) {
        de.schlichtherle.io.File 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.RUN,runDir,
                    WepsFileChooser.SELECT);
            wfc.setCurrentDirectory(new de.schlichtherle.io.File(runDir));
            if (wfc.showDialog(objectforIcon) == JFileChooser.APPROVE_OPTION) {
                sf = new File(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 File(runDir)).exists()) {
                rfd.readRunFile(runDir);
            } else {
                //System.err.println("CS_m : current run does not exist " + runDir);
                return null;
            }
        }
        
        OutputViewer op = new OutputViewer("Debugging 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.
     */
    protected void JBOK_actionPerformed(java.awt.event.ActionEvent event) {
        // to do: code goes here.
//		System.exit(0);
        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.
     */
    protected void JBPrint_actionPerformed(java.awt.event.ActionEvent event) {
        // to do: code goes here.
        PrintUtilities.printComponent(JTA_text);
    }
    
    void loadWepsData(String runFilePathName, JTextArea JTA_text) {
        ObjectInputStream objStream = null;
        File inpfil = new File((new File(runDirectory)).getParentFile(),
                RunFileData.WepsData);
        try {
            FileInputStream outStream = new FileInputStream(inpfil);
            objStream = new ObjectInputStream(outStream);
            Hashtable ht = (Hashtable) objStream.readObject();
//			Enumeration e = ht.keys();
//			Set e = ht.keys();
            Vector e = new Vector(ht.keySet());
            Collections.sort(e);
//			while (e.hasMoreElements()) {
            for (Iterator vi = e.iterator(); vi.hasNext(); ) {
                Object key = vi.next();
                Object value = ht.get(key);
                String outVal = "";
                try {
                    outVal = ((String) key) + " -> " + ((String) value);
                } catch (java.lang.ClassCastException g) {
                    outVal = "Invalid property " + 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();
        }   // catch
    }
    
    
    /**
     * 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")
    protected void JCBFileNames_itemStateChanged(java.awt.event.ItemEvent event) {
        if(ItemEvent.SELECTED != event.getStateChange()){
            return;
        }
        Thread t = new Thread("OutputViewer") {
            public void run() {
                // to do: code goes here.
                ProgressMonitor progress = null;
                File file = new File(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 {
                    try {
                        BufferedReader in = new BufferedReader(new FileReader(file));
                        String temp;
                        while((temp = in.readLine())!=null) {
                            progress.setProgress(temp.length());
                            JTA_text.append(temp + "\n");
                        }
                        progress.close();
                        in.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();
    }
    
    /**
     * 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.
     */
    protected void OutputViewerN_componentResized(java.awt.event.ComponentEvent event) {
        // to do: code goes here.
        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();
    }
    
    
}
