/*
 * ESLGui.java
 *
 * Created on Jun 30, 2010, 10:18:35 AM
 *
 * Copyright (C) 2010, Anthony Cosgrove <acosgrov@gmail.com>
 *
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the License.
 */

/*
 * The beginnings of a java GUI CLI. Just to warn you it is still very very
 * crude. There's no exception handling yet so you may come across errors.
 * I'm also still working out the colors on the console so it all looks like
 * what we're used to.
 *
 * Usage: You'll need to compile javamod in the sources libs/esl. Make javamod
 * and you should be left with esl.jar and libesljni.so. Incude esl.jar in your
 * project and put libesljni.so somewhere in your CLASSPATH or adjust
 * System.load(path_to_file) in main().
 *
 */

package my.gui;

import java.awt.event.KeyEvent;
import java.util.*;

/**
 *
 * @author acosgrove
 */
public class ESLGui extends javax.swing.JFrame {

    ESLStuff myesl = new ESLStuff();

    /** Creates new form ESLGui */
    public ESLGui() {
        initComponents();
    }

    /** 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() {

        jTabbedPane1 = new javax.swing.JTabbedPane();
        settingsPanel = new javax.swing.JPanel();
        hostNameLabel = new javax.swing.JLabel();
        portLabel = new javax.swing.JLabel();
        passwordLabel = new javax.swing.JLabel();
        hostnameTextField = new javax.swing.JTextField();
        portTextField = new javax.swing.JTextField();
        passwordField = new javax.swing.JPasswordField();
        connectButton = new javax.swing.JButton();
        disconnectButton = new javax.swing.JButton();
        consolePanel = new javax.swing.JPanel();
        consoleInputTextField = new javax.swing.JTextField();
        consoleScrollCheckBox = new javax.swing.JCheckBox();
        consoleScrollPane = new javax.swing.JScrollPane();
        consoleTextArea = new javax.swing.JTextArea();
        eventsPanel = new javax.swing.JPanel();
        eventsScrollPanel = new javax.swing.JScrollPane();
        eventsTextArea = new javax.swing.JTextArea();
        eventsScrollCheckBox = new javax.swing.JCheckBox();
        historyPanel = new javax.swing.JPanel();
        historyScrollPane = new javax.swing.JScrollPane();
        historyTextArea = new javax.swing.JTextArea();
        historyScrollCheckBox = new javax.swing.JCheckBox();
        clearHistoryButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("FreeSWITCH™GUI-fied CLI");
        setBounds(new java.awt.Rectangle(0, 0, 0, 0));
        setMinimumSize(new java.awt.Dimension(800, 600));

        jTabbedPane1.setMaximumSize(new java.awt.Dimension(800, 600));
        jTabbedPane1.setMinimumSize(new java.awt.Dimension(320, 240));
        jTabbedPane1.setPreferredSize(new java.awt.Dimension(640, 480));

        hostNameLabel.setText("Hostname");

        portLabel.setText("Port");

        passwordLabel.setText("Password");

        hostnameTextField.setText("127.0.0.1");

        portTextField.setText("8021");

        passwordField.setText("ClueCon");

        connectButton.setText("Connect");
        connectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectButtonActionPerformed(evt);
            }
        });

        disconnectButton.setText("Disconnect");
        disconnectButton.setToolTipText("Disconnect from FS");
        disconnectButton.setEnabled(false);
        disconnectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                disconnectButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout settingsPanelLayout = new javax.swing.GroupLayout(settingsPanel);
        settingsPanel.setLayout(settingsPanelLayout);
        settingsPanelLayout.setHorizontalGroup(
            settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(settingsPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(hostNameLabel)
                    .addComponent(portLabel)
                    .addComponent(passwordLabel)
                    .addComponent(connectButton))
                .addGap(18, 18, 18)
                .addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(disconnectButton)
                    .addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                        .addComponent(passwordField, javax.swing.GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE)
                        .addComponent(portTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE)
                        .addComponent(hostnameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE)))
                .addContainerGap(380, Short.MAX_VALUE))
        );
        settingsPanelLayout.setVerticalGroup(
            settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(settingsPanelLayout.createSequentialGroup()
                .addGap(12, 12, 12)
                .addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(hostNameLabel)
                    .addComponent(hostnameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE, false)
                    .addComponent(portLabel)
                    .addComponent(portTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(passwordLabel)
                    .addComponent(passwordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(connectButton)
                    .addComponent(disconnectButton))
                .addGap(271, 271, 271))
        );

        jTabbedPane1.addTab("Settings", settingsPanel);

        consolePanel.setBorder(null);

        consoleInputTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                consoleInputTextFieldKeyTyped(evt);
            }
            public void keyPressed(java.awt.event.KeyEvent evt) {
                consoleInputTextFieldKeyPressed(evt);
            }
        });

        consoleScrollCheckBox.setSelected(true);
        consoleScrollCheckBox.setText("auto-scroll");

        consoleTextArea.setBackground(java.awt.Color.black);
        consoleTextArea.setColumns(20);
        consoleTextArea.setEditable(false);
        consoleTextArea.setFont(new java.awt.Font("SansSerif", 0, 12));
        consoleTextArea.setForeground(java.awt.Color.white);
        consoleTextArea.setLineWrap(true);
        consoleTextArea.setRows(5);
        consoleScrollPane.setViewportView(consoleTextArea);

        javax.swing.GroupLayout consolePanelLayout = new javax.swing.GroupLayout(consolePanel);
        consolePanel.setLayout(consolePanelLayout);
        consolePanelLayout.setHorizontalGroup(
            consolePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, consolePanelLayout.createSequentialGroup()
                .addComponent(consoleInputTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 495, Short.MAX_VALUE)
                .addGap(30, 30, 30)
                .addComponent(consoleScrollCheckBox)
                .addContainerGap())
            .addComponent(consoleScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 628, Short.MAX_VALUE)
        );
        consolePanelLayout.setVerticalGroup(
            consolePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, consolePanelLayout.createSequentialGroup()
                .addComponent(consoleScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 390, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(consolePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(consoleScrollCheckBox)
                    .addComponent(consoleInputTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        jTabbedPane1.addTab("Console", consolePanel);

        eventsTextArea.setBackground(java.awt.Color.black);
        eventsTextArea.setColumns(20);
        eventsTextArea.setEditable(false);
        eventsTextArea.setForeground(java.awt.Color.white);
        eventsTextArea.setRows(5);
        eventsScrollPanel.setViewportView(eventsTextArea);

        eventsScrollCheckBox.setSelected(true);
        eventsScrollCheckBox.setText("auto-scroll");

        javax.swing.GroupLayout eventsPanelLayout = new javax.swing.GroupLayout(eventsPanel);
        eventsPanel.setLayout(eventsPanelLayout);
        eventsPanelLayout.setHorizontalGroup(
            eventsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, eventsPanelLayout.createSequentialGroup()
                .addContainerGap(525, Short.MAX_VALUE)
                .addComponent(eventsScrollCheckBox)
                .addContainerGap())
            .addComponent(eventsScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 628, Short.MAX_VALUE)
        );
        eventsPanelLayout.setVerticalGroup(
            eventsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, eventsPanelLayout.createSequentialGroup()
                .addComponent(eventsScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 399, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(eventsScrollCheckBox)
                .addContainerGap())
        );

        jTabbedPane1.addTab("Events", eventsPanel);

        historyTextArea.setBackground(java.awt.Color.black);
        historyTextArea.setColumns(20);
        historyTextArea.setEditable(false);
        historyTextArea.setFont(new java.awt.Font("SansSerif", 0, 16));
        historyTextArea.setForeground(java.awt.Color.white);
        historyTextArea.setRows(5);
        historyScrollPane.setViewportView(historyTextArea);
        updateHistory();

        historyScrollCheckBox.setSelected(true);
        historyScrollCheckBox.setText("auto-scroll");

        clearHistoryButton.setText("Clear history");
        clearHistoryButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                clearHistoryButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout historyPanelLayout = new javax.swing.GroupLayout(historyPanel);
        historyPanel.setLayout(historyPanelLayout);
        historyPanelLayout.setHorizontalGroup(
            historyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, historyPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(clearHistoryButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 421, Short.MAX_VALUE)
                .addComponent(historyScrollCheckBox)
                .addContainerGap())
            .addComponent(historyScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 628, Short.MAX_VALUE)
        );
        historyPanelLayout.setVerticalGroup(
            historyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, historyPanelLayout.createSequentialGroup()
                .addComponent(historyScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(historyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(historyScrollCheckBox)
                    .addComponent(clearHistoryButton))
                .addContainerGap())
        );

        jTabbedPane1.addTab("History", historyPanel);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jTabbedPane1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        jTabbedPane1.getAccessibleContext().setAccessibleName("Main");

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

    private void consoleInputTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_consoleInputTextFieldKeyTyped
        int i = evt.getKeyChar();

        // When ENTER is pressed process command and add to history

        if (i == KeyEvent.VK_ENTER) {
            String input = consoleInputTextField.getText();
            if (!input.equals("")) {
                myesl.command(input);
                addToHistory(input);
                consoleInputTextField.setText(null);
            }
            else {
                consoleTextArea.append("\n");
            }
        }
    }//GEN-LAST:event_consoleInputTextFieldKeyTyped

    private void clearHistoryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearHistoryButtonActionPerformed
        clearHistory();
    }//GEN-LAST:event_clearHistoryButtonActionPerformed

    private void consoleInputTextFieldKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_consoleInputTextFieldKeyPressed
        int i = evt.getKeyCode();

        // This code handles navigating the history

        if (i == KeyEvent.VK_UP) {
            if (cmdHistLit.hasPrevious()) {
                consoleInputTextField.setText(cmdHistLit.previous().toString());
            }
        }

        if (i == KeyEvent.VK_DOWN) {
            if (cmdHistLit.hasNext()) {
                consoleInputTextField.setText(cmdHistLit.next().toString());
            }
        }
    }//GEN-LAST:event_consoleInputTextFieldKeyPressed

    private void connectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectButtonActionPerformed
        doConnect();
    }//GEN-LAST:event_connectButtonActionPerformed

    private void disconnectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_disconnectButtonActionPerformed
        doDisconnect();
    }//GEN-LAST:event_disconnectButtonActionPerformed

    private void addToHistory(String input) {
        // Add last command to history and update
        // Make sure we are at the end of the iterator
        while (cmdHistLit.hasNext()) {
            cmdHistLit.next();
        }
        cmdHistLit.add(input);
        updateHistory();
        System.out.println(cmdHistLit.nextIndex());
    }

    private void updateHistory() {
        // Check if history list is empty - refresh the iterator first
        cmdHistIt = cmdHistory.iterator();
        if (cmdHistory.isEmpty()) {
            historyTextArea.setText("No history");
        }
        else {
            historyTextArea.setText(null);
            int i = 0;
            while (cmdHistIt.hasNext()) {
                i++;
                historyTextArea.append(i + ". " + cmdHistIt.next() + "\n");
            }
        }
    }

    private void clearHistory() {
        // Clear out the list and update
        cmdHistory.clear();
        cmdHistLit = cmdHistory.listIterator();
        updateHistory();
    }

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        System.load("/lib/libesljni.so");
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ESLGui().setVisible(true);
            }
        });
    }


    private void doConnect() {

        if (myesl.connect(hostnameTextField.getText(), portTextField.getText(), String.valueOf(passwordField.getPassword()))) {
            jTabbedPane1.setSelectedIndex(1);
            connectButton.setEnabled(false);
            disconnectButton.setEnabled(true);
        }
        //connectToggleButton.setEnabled(false);
        // Thread to take care of incoming data

        new Thread() {
            @Override
            public void run() {
                System.out.println("Starting data dispatcher thread");
                while (myesl.isConnected()) {
                    String[] data = myesl.getData();
                            //if (consoleText != null) {
                            //if (consoleText.contains("[INFO]")) { consoleTextArea.setForeground(Color.green); }
                            //if (consoleText.contains("[NOTICE]")) { consoleTextArea.setForeground(Color.blue); }
                            //if (consoleText.contains("[ERR]")) { consoleTextArea.setForeground(Color.red); }
                            //}

                    consoleTextArea.append(data[0]);

                    // Auto-scroll code for the console tab

                    if (consoleScrollCheckBox.isSelected()) {
                        consoleTextArea.setCaretPosition(consoleTextArea.getDocument().getLength());
                    }
                    eventsTextArea.append(data[1]);
                    // Auto-scroll code for the events tab
                    if (eventsScrollCheckBox.isSelected()) {
                        eventsTextArea.setCaretPosition(eventsTextArea.getDocument().getLength());
                    }
                }
                System.out.println("Exiting data dispatcher thread");
            }
        }.start();
    }

    private void doDisconnect() {
        disconnectButton.setEnabled(false);
        connectButton.setEnabled(true);
        myesl.disconnect();
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton clearHistoryButton;
    private javax.swing.JButton connectButton;
    private javax.swing.JTextField consoleInputTextField;
    private javax.swing.JPanel consolePanel;
    private javax.swing.JCheckBox consoleScrollCheckBox;
    private javax.swing.JScrollPane consoleScrollPane;
    private javax.swing.JTextArea consoleTextArea;
    private javax.swing.JButton disconnectButton;
    private javax.swing.JPanel eventsPanel;
    private javax.swing.JCheckBox eventsScrollCheckBox;
    private javax.swing.JScrollPane eventsScrollPanel;
    private javax.swing.JTextArea eventsTextArea;
    private javax.swing.JPanel historyPanel;
    private javax.swing.JCheckBox historyScrollCheckBox;
    private javax.swing.JScrollPane historyScrollPane;
    private javax.swing.JTextArea historyTextArea;
    private javax.swing.JLabel hostNameLabel;
    private javax.swing.JTextField hostnameTextField;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JPasswordField passwordField;
    private javax.swing.JLabel passwordLabel;
    private javax.swing.JLabel portLabel;
    private javax.swing.JTextField portTextField;
    private javax.swing.JPanel settingsPanel;
    // End of variables declaration//GEN-END:variables

    private ArrayList<String> cmdHistory = new ArrayList<String>();
    private Iterator cmdHistIt = cmdHistory.iterator();
    private ListIterator cmdHistLit = cmdHistory.listIterator();
}
