/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import interpreter.tools.DefaultReader;
import interpreter.exceptions.BuildException;
import interpreter.*;
import interpreter.tools.Input;
import interpreter.tools.Output;
import interpreter.tree.FTree;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Vector;
import javax.swing.JOptionPane;
import javax.swing.Timer;

/**
 *
 * @author LMO
 */
public class Main extends javax.swing.JFrame implements ActionListener {

    /**
     * Creates new form Main
     */
    Timer timer = new Timer(10, this);
    Interpreter interpreter;
    int maxMemory = 0;

    public Main() {
        initComponents();
        memoryArea.setEditable(false);
        nextButton.setEnabled(false);
        stopButton.setEnabled(false);
        setMemory();
    }

    void setMemory() {
        Runtime rt = Runtime.getRuntime();
        rt.freeMemory();
        freeMemory.setValue(100 - (int) (100.0 * rt.freeMemory() / rt.totalMemory()));
        maxMemory = (int) Math.max(maxMemory, rt.totalMemory() - rt.freeMemory());
        maxMemoryField.setText("" + (rt.totalMemory() - rt.freeMemory()) / (1024 * 1024) + "MB / " + rt.totalMemory() / (1024 * 1024) + "MB");
    }

    void init() {
        lineField.setText("");
        errorArea.setText("");
        memoryArea.setText("");
    }

    void finish() {
        timer.stop();
        stopButton.setEnabled(false);
        System.runFinalization();
        System.gc();
    }

    void declare() {
        interpreter = new Interpreter(new DefaultReader(), new Input() {

            @Override
            public Object read() {
                Object ret = null;
                String in = JOptionPane.showInputDialog(null, "", "оруул", JOptionPane.PLAIN_MESSAGE);
                try {
                    ret = Long.parseLong(in);
                } catch (NumberFormatException ex) {
                    try {
                        ret = Double.parseDouble(in);
                    } catch (NumberFormatException ex1) {
                        ret = in;
                    }
                }
                return ret;
            }
        }, new Output() {

            @Override
            public void write(String out) {
                errorArea.setText(errorArea.getText() + out);
            }
        }, new HashMap<String, FTree>(), 0);
    }

    void run(boolean debug) {
        nextButton.setEnabled(debug);
        nameField.setEditable(!debug);
        stopButton.setEnabled(true);
        init();
        declare();
        interpreter.interpret(nameField.getText(), new Vector<Object>(), debug);
        timer.start();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        debugButton = new javax.swing.JButton();
        runButton = new javax.swing.JButton();
        nextButton = new javax.swing.JButton();
        nameField = new javax.swing.JTextField();
        lineField = new javax.swing.JTextField();
        stopButton = new javax.swing.JButton();
        maxMemoryField = new javax.swing.JTextField();
        freeMemory = new javax.swing.JProgressBar();
        jSplitPane2 = new javax.swing.JSplitPane();
        errorScroll = new javax.swing.JScrollPane();
        errorArea = new javax.swing.JTextArea();
        memorySroll = new javax.swing.JScrollPane();
        memoryArea = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        debugButton.setText("debug");
        debugButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                debugButtonActionPerformed(evt);
            }
        });

        runButton.setText("run");
        runButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                runButtonActionPerformed(evt);
            }
        });

        nextButton.setText("next");
        nextButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nextButtonActionPerformed(evt);
            }
        });

        nameField.setText("code");

        stopButton.setText("stop");
        stopButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stopButtonActionPerformed(evt);
            }
        });

        jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

        errorArea.setColumns(20);
        errorArea.setFont(new java.awt.Font("Courier New", 0, 12)); // NOI18N
        errorArea.setForeground(new java.awt.Color(255, 0, 0));
        errorArea.setRows(5);
        errorScroll.setViewportView(errorArea);

        jSplitPane2.setRightComponent(errorScroll);

        memoryArea.setColumns(20);
        memoryArea.setFont(new java.awt.Font("Courier New", 0, 12)); // NOI18N
        memoryArea.setRows(5);
        memoryArea.setWrapStyleWord(true);
        memorySroll.setViewportView(memoryArea);

        jSplitPane2.setTopComponent(memorySroll);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(nameField, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(lineField))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(debugButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(nextButton, javax.swing.GroupLayout.PREFERRED_SIZE, 103, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(stopButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 200, Short.MAX_VALUE)
                        .addComponent(runButton, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(maxMemoryField)
                    .addComponent(freeMemory, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jSplitPane2))
                .addContainerGap())
        );

        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {debugButton, nextButton, runButton, stopButton});

        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(debugButton)
                    .addComponent(nextButton)
                    .addComponent(runButton)
                    .addComponent(stopButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(nameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lineField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 340, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(maxMemoryField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(4, 4, 4)
                .addComponent(freeMemory, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void debugButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_debugButtonActionPerformed
        run(true);
    }//GEN-LAST:event_debugButtonActionPerformed

    private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_runButtonActionPerformed
        run(false);
    }//GEN-LAST:event_runButtonActionPerformed
    private void nextButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextButtonActionPerformed
        interpreter.next();
    }//GEN-LAST:event_nextButtonActionPerformed

    private void stopButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stopButtonActionPerformed
        nextButton.setEnabled(false);
        nameField.setEditable(true);
        if (interpreter != null) {
            interpreter.stop();
        }
        finish();
    }//GEN-LAST:event_stopButtonActionPerformed

    @Override
    public void actionPerformed(ActionEvent e) {
        setMemory();
        this.lineField.setText(interpreter.getInfo() + " will run");
        try {
            if (interpreter.isFinished()) {
                finish();
            }
            this.memoryArea.setText(interpreter.getMemory().toString());
            try {
                interpreter.checkError();
            } catch (BuildException ex) {
                errorArea.setText(errorArea.getText() + "\n" + ex.getName() + "@" + ex.getLine() + ": " + ex.toString());
                throw ex;
            }
        } catch (Exception ex) {
            if (!ex.getClass().getSuperclass().equals(BuildException.class)) {
                errorArea.setText(errorArea.getText() + "\n" + ex.toString());
            }
            nextButton.setEnabled(false);
            nameField.setEditable(true);
            finish();
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        try {
            //javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
            javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            //javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Main().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton debugButton;
    private javax.swing.JTextArea errorArea;
    private javax.swing.JScrollPane errorScroll;
    private javax.swing.JProgressBar freeMemory;
    private javax.swing.JSplitPane jSplitPane2;
    private javax.swing.JTextField lineField;
    private javax.swing.JTextField maxMemoryField;
    private javax.swing.JTextArea memoryArea;
    private javax.swing.JScrollPane memorySroll;
    private javax.swing.JTextField nameField;
    private javax.swing.JButton nextButton;
    private javax.swing.JButton runButton;
    private javax.swing.JButton stopButton;
    // End of variables declaration//GEN-END:variables
}
