/*
 * Copyright 2021 Matt Jamesson <scifidryer@gmail.com>.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package modbusmechanic;
import javax.swing.table.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
import purejavacomm.CommPortIdentifier;
import purejavacomm.SerialPort;
import java.io.*;

/**
 *
 * @author Matt Jamesson <scifidryer@gmail.com>
 */
public class RTUScannerFrame extends javax.swing.JFrame {

    /**
     * Creates new form RTUScannerFrame
     */
    public ScannerRenderer sr = new ScannerRenderer();
    int count = 1;
    boolean keepScanning = false;
    RTUScannerThread thread = null;
    public RTUScannerFrame() {
        initComponents();
        DefaultTableModel model = new DefaultTableModel();
        for (int i = 0; i < 16; i++)
        {
            model.addColumn("");
        }
        for (int i = 0; i < 16; i++)
        {
            model.addRow(generateRow());
        }
        
        
        scannerTable.setModel(model);
        for (int i = 0; i < 16; i++)
        {
            scannerTable.getColumnModel().getColumn(i).setCellRenderer(sr);
        }
    }
    public Object[] generateRow()
    {
        ArrayList<Object> rows = new ArrayList();
        
        for (int i = 0; i < 16; i++)
        {
            if (count < 248)
            {
                rows.add("" + count);
                count++;
            }
        }
        return rows.toArray();
    }
   class ScannerRenderer extends DefaultTableCellRenderer {
   Color color;
   int nodeNum = 0;
   ArrayList<Color> cellColors = new ArrayList();
   ArrayList<String> toolTips = new ArrayList();
   public ScannerRenderer() {
      super();
      initColors();
   }
   public Color getNodeColor(int node)
   {
       return cellColors.get(node-1);
   }
   public void setNodeColor(int node, Color color)
   {
       setCellAttribs(node, color, null);
   }
   public void setCellAttribs(int node, Color aColor, String toolTip)
   {
       cellColors.set(node-1, aColor);
       if (toolTip != null)
       {
           toolTips.set(node-1, toolTip);
       }
   }
   public void initColors()
   {
       cellColors.clear();
       toolTips.clear();
       for (int i = 0; i < 256; i++)
       {
           toolTips.add(null);
           cellColors.add(Color.WHITE);
       }
   }
   public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,   boolean hasFocus, int row, int column) {
        JLabel cell = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        int currentNode = row*16 + column;
        cell.setBackground(cellColors.get(currentNode));
        String toolTip = toolTips.get(currentNode);
        if (toolTip != null)
        {
            cell.setToolTipText(toolTip);
        }
        return cell;
   }
}

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

        jTextField1 = new javax.swing.JTextField();
        jPanel1 = new javax.swing.JPanel();
        jPanel7 = new javax.swing.JPanel();
        jLabel14 = new javax.swing.JLabel();
        jPanel2 = new javax.swing.JPanel();
        jLabel12 = new javax.swing.JLabel();
        comPortSelector = new javax.swing.JComboBox<>();
        jLabel13 = new javax.swing.JLabel();
        baudRateSelector = new javax.swing.JComboBox<>();
        jLabel15 = new javax.swing.JLabel();
        dataBitsField = new javax.swing.JTextField();
        jLabel16 = new javax.swing.JLabel();
        stopBitsField = new javax.swing.JTextField();
        jPanel5 = new javax.swing.JPanel();
        jLabel17 = new javax.swing.JLabel();
        paritySelector = new javax.swing.JComboBox<>();
        jLabel1 = new javax.swing.JLabel();
        timeoutField = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        jPanel4 = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        functionCodeSelector = new javax.swing.JComboBox<>();
        jLabel4 = new javax.swing.JLabel();
        scanRegisterField = new javax.swing.JTextField();
        jPanel3 = new javax.swing.JPanel();
        scanButton = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        scannerTable = new javax.swing.JTable();

        jTextField1.setText("jTextField1");

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(), javax.swing.BoxLayout.Y_AXIS));

        jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.Y_AXIS));

        jLabel14.setFont(new java.awt.Font("Tahoma", 1, 16)); // NOI18N
        jLabel14.setText("RTU Scanner Serial settings");
        jPanel7.add(jLabel14);

        jPanel1.add(jPanel7);

        jLabel12.setText("Port");
        jPanel2.add(jLabel12);

        comPortSelector.setModel(new DefaultComboBoxModel(ModbusMechanic.getPortNames()));
        comPortSelector.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                comPortSelectorActionPerformed(evt);
            }
        });
        jPanel2.add(comPortSelector);

        jLabel13.setText("Baud");
        jPanel2.add(jLabel13);

        baudRateSelector.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "4800", "9600", "14400", "19200", "38400", "57600", "115200" }));
        jPanel2.add(baudRateSelector);

        jLabel15.setText("Data bits");
        jPanel2.add(jLabel15);

        dataBitsField.setColumns(2);
        dataBitsField.setText("8");
        jPanel2.add(dataBitsField);

        jLabel16.setText("Stop bits");
        jPanel2.add(jLabel16);

        stopBitsField.setColumns(2);
        stopBitsField.setText("1");
        jPanel2.add(stopBitsField);

        jPanel1.add(jPanel2);

        jLabel17.setText("Parity");
        jPanel5.add(jLabel17);

        paritySelector.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "None", "Odd", "Even", "Mark", "Space" }));
        paritySelector.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                paritySelectorActionPerformed(evt);
            }
        });
        jPanel5.add(paritySelector);

        jLabel1.setText("Scan timeout");
        jPanel5.add(jLabel1);

        timeoutField.setColumns(3);
        timeoutField.setText("20");
        timeoutField.setToolTipText("");
        timeoutField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                timeoutFieldActionPerformed(evt);
            }
        });
        jPanel5.add(timeoutField);

        jLabel2.setText("ms");
        jPanel5.add(jLabel2);

        jPanel1.add(jPanel5);

        jLabel3.setText("Function Code");
        jPanel4.add(jLabel3);

        functionCodeSelector.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Read Coils", "Read Discrete Inputs", "Read Holding Registers", "Read Input Registers" }));
        functionCodeSelector.setSelectedIndex(2);
        jPanel4.add(functionCodeSelector);

        jLabel4.setText("Scan Register");
        jPanel4.add(jLabel4);

        scanRegisterField.setColumns(4);
        scanRegisterField.setText("1");
        jPanel4.add(scanRegisterField);

        jPanel1.add(jPanel4);

        scanButton.setText("Scan");
        scanButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                scanButtonActionPerformed(evt);
            }
        });
        jPanel3.add(scanButton);

        jPanel1.add(jPanel3);

        getContentPane().add(jPanel1);

        scannerTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {

            }
        ));
        scannerTable.setEnabled(false);
        jScrollPane1.setViewportView(scannerTable);

        getContentPane().add(jScrollPane1);

        setBounds(0, 0, 476, 470);
    }// </editor-fold>//GEN-END:initComponents

    private void scanButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scanButtonActionPerformed
        if (thread == null || !thread.isRunning())
        {
            sr.initColors();
            scanButton.setText("Stop");
            keepScanning = true;
            thread = new RTUScannerThread(this);
            thread.start();
        }
        else
        {
            thread.stopRunning();
            scanButton.setText("Scan");
        }
    }//GEN-LAST:event_scanButtonActionPerformed

    private void comPortSelectorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comPortSelectorActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_comPortSelectorActionPerformed

    private void paritySelectorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_paritySelectorActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_paritySelectorActionPerformed

    private void timeoutFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeoutFieldActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_timeoutFieldActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(RTUScannerFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(RTUScannerFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(RTUScannerFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(RTUScannerFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new RTUScannerFrame().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    public javax.swing.JComboBox<String> baudRateSelector;
    public javax.swing.JComboBox<String> comPortSelector;
    public javax.swing.JTextField dataBitsField;
    public javax.swing.JComboBox<String> functionCodeSelector;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel13;
    private javax.swing.JLabel jLabel14;
    private javax.swing.JLabel jLabel15;
    private javax.swing.JLabel jLabel16;
    private javax.swing.JLabel jLabel17;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextField jTextField1;
    public javax.swing.JComboBox<String> paritySelector;
    public javax.swing.JButton scanButton;
    public javax.swing.JTextField scanRegisterField;
    private javax.swing.JTable scannerTable;
    public javax.swing.JTextField stopBitsField;
    public javax.swing.JTextField timeoutField;
    // End of variables declaration//GEN-END:variables
}
