/*
 * AlarmGpioView.java
 * 
 * Copyright (c) 2003-2004 Digi International
 * This program and the information contained in it is confidential and
 * proprietary to Digi International and may not be used, copied, or re-
 * produced without the prior written permission of Digi International.
 * 
 */

package com.digi.config.ui;

import com.digi.config.core.*;
import com.digi.config.util.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.net.*;




/** 
 * This class is a view panel that shows the GPIO Alarm
 * settings for the ConnectMe device
 * 
 * This view can be embedded in other panels as desired.
 */


public class AlarmGpioView extends ConfigViewImpl {
    /** A KvpNode that holds just the fields used in this view */
    KvpNode viewSettingTree;
    /** listens to the device for changes to settings */
    DeviceChangeListener settingChangeListener;
    /** listens to changes in controls in the view */
    ControlChangeAdapter fieldListener;
    /** Panel that holds the view content */
    GridContentPanel content;
    GridContentPanel alarmContent;
    GridContentPanel smtpContent;
    GridContentPanel listContent;
    GridContentPanel detailContent;
    int alarmCount = 0;
    Device.DeviceModelInfo modelInfo=null;

    // Data fields currently used in this view
    KvpField alarmsEnabledKvpField;
    KvpField alarmSmtpServerKvpField;
    KvpField alarmSmtpFromKvpField;

    KvpField alarmEnabledKvpField[];
    KvpField alarmToKvpField[];
    KvpField alarmCcKvpField[];
    KvpField alarmSubjectKvpField[];
    KvpField alarmPriorityKvpField[];
    KvpField alarmTriggerModeKvpField[];
    KvpField alarmPatternKvpField[];
    KvpField alarmPatternPortKvpField[];
    KvpField alarmMonitorMaskKvpField[];
    KvpField alarmStateMaskKvpField[];
    KvpField alarmTriggerIntervalTimeKvpField[];
    KvpField alarmSendReminderEnabledKvpField[];
    KvpField alarmReminderIntervalTimeKvpField[];


    // UI Controls for each field
    JCheckBox           alarmsEnabled_UIC;
    JTextField          alarmSmtpServer_UIC;
    JTextField          alarmSmtpFrom_UIC;

    JCheckBox           alarmEnabled_UIC[];
    JTextField          alarmTo_UIC[];
    JTextField          alarmCc_UIC[];
    JTextField          alarmSubject_UIC[];
    JComboBox           alarmPriority_UIC[];
    JComboBox           alarmTriggerMode_UIC[];
    GridContentPanel    patternOptionsContent[];
    GridContentPanel    gpioOptionsContent[];
    JTextField          alarmPattern_UIC[];
    JComboBox           alarmPatternPort_UIC[];
    BitMaskPanel        alarmTrigger_UIC[];
    JTextField          alarmTriggerIntervalTime_UIC[];
    JCheckBox           alarmSendRemindersEnabled_UIC[];
    JTextField          alarmReminderIntervalTime_UIC[];

    JTextField          alarmMonitorMask_UIC[];
    JTextField          alarmStateMask_UIC[];

    /**
     * Basic constructor. Sets up the tree view and the edit panel.
     */
    public AlarmGpioView() throws Exception {
        super(true);
        // create a cache of settings displayed in this view and listen for changes to the device settings
        viewSettingTree = new KvpNode();
        settingChangeListener = new DeviceChangeListener() {
            public void deviceChanged(DeviceChangeEvent e) {
                SystemLog.debug("AlarmGpioView was notified that device settings changed");
                refreshViewData();
                refreshViewControls();
            }
        };
        // create a listener that will detect when a user edits the field values and update the appropriate view setting fields
        fieldListener = new ControlChangeAdapter() {
            public void changePerformed(Object source, ActionEvent ae, FocusEvent fe) {
                //SystemLog.debug("AlarmGpioView was notified that field "+source.toString()+" changed.");
                if (modelInfo==null) {
                    return;
                }
                if (source==alarmsEnabled_UIC) {
                    alarmsEnabledKvpField.setStringValue(RciProtocol.toString(alarmsEnabled_UIC.isSelected()));
                    alarmContent.setContainerEnabled(alarmsEnabled_UIC.isSelected());

                    // Update Alarm Enable/Disable Status
                    if (alarmsEnabled_UIC.isSelected()) {
                        for (int i=0;i<alarmCount; i++) {
                            boolean gpio_selected = true;
                            String triggerMode = alarmTriggerMode_UIC[i].getSelectedItem().toString();
                            if (triggerMode.equalsIgnoreCase("gpio"))
                                gpio_selected = true;
                            else if (triggerMode.equalsIgnoreCase("pattern_match"))
                                gpio_selected = false;

                            alarmPattern_UIC[i].setEnabled(!gpio_selected);
                            alarmTrigger_UIC[i].setEnabled(gpio_selected);
                            alarmTriggerIntervalTime_UIC[i].setEnabled(gpio_selected);
                            alarmSendRemindersEnabled_UIC[i].setEnabled(gpio_selected);
                            alarmReminderIntervalTime_UIC[i].setEnabled(gpio_selected);
                        }
                    }
                } else if (source==alarmSmtpServer_UIC) {
                    alarmSmtpServerKvpField.setStringValue(alarmSmtpServer_UIC.getText());
                } else if (source==alarmSmtpFrom_UIC) {
                    alarmSmtpFromKvpField.setStringValue(alarmSmtpFrom_UIC.getText());
                } else {
                    // Next, check to see if it was one of the ALARM list fields
                    for (int i=0;i<alarmCount; i++) {
                        if (source==alarmEnabled_UIC[i]) {
                            alarmEnabledKvpField[i].setStringValue(RciProtocol.toString(alarmEnabled_UIC[i].isSelected()));
                        } else if (source==alarmTo_UIC[i]) {
                            alarmToKvpField[i].setStringValue(alarmTo_UIC[i].getText());
                        } else if (source==alarmCc_UIC[i]) {
                            alarmCcKvpField[i].setStringValue(alarmCc_UIC[i].getText());
                        } else if (source==alarmSubject_UIC[i]) {
                            alarmSubjectKvpField[i].setStringValue(alarmSubject_UIC[i].getText());
                        } else if (source==alarmPriority_UIC[i]) {
                            alarmPriorityKvpField[i].setStringValue(alarmPriority_UIC[i].getSelectedItem().toString());
                        } else if (source==alarmTriggerMode_UIC[i]) {
                            alarmTriggerModeKvpField[i].setStringValue(alarmTriggerMode_UIC[i].getSelectedItem().toString());
                            boolean gpio_selected = false;
                            String triggerMode = alarmTriggerMode_UIC[i].getSelectedItem().toString();
                            if (triggerMode.equalsIgnoreCase("gpio")) {
                                gpio_selected = true;
                            }
                            patternOptionsContent[i].setVisible(!gpio_selected);
                            gpioOptionsContent[i].setVisible(gpio_selected);
                            alarmPattern_UIC[i].setEnabled(!gpio_selected);
                            alarmPatternPort_UIC[i].setEnabled(!gpio_selected);
                            boolean hasGpio = modelInfo.getGpioCount()>0;
                            if (hasGpio) {
                                alarmTrigger_UIC[i].setEnabled(gpio_selected);
                                alarmTriggerIntervalTime_UIC[i].setEnabled(gpio_selected);
                                alarmSendRemindersEnabled_UIC[i].setEnabled(gpio_selected);
                                alarmReminderIntervalTime_UIC[i].setEnabled(gpio_selected);
                            }
                        } else if (source==alarmPattern_UIC[i]) {
                            alarmPatternKvpField[i].setStringValue(alarmPattern_UIC[i].getText());
                        } else if (source==alarmPatternPort_UIC[i]) {
                            alarmPatternPortKvpField[i].setStringValue(alarmPatternPort_UIC[i].getSelectedItem().toString());
                        } else if (source==alarmTrigger_UIC[i]) {
                            int triggerBits[] = alarmTrigger_UIC[i].getBits();
                            SystemLog.debug("Trigger changed to "+triggerBits);
                            for (int j=0;j<triggerBits.length;j++) {
                                SystemLog.debug("pin["+j+"] = "+triggerBits[j]);
                            }
                            alarmMonitorMaskKvpField[i].setStringValue(computeMonitorMask(triggerBits));
                            alarmStateMaskKvpField[i].setStringValue(computeStateMask(triggerBits));
                        } else if (source==alarmTriggerIntervalTime_UIC[i]) {
                            alarmTriggerIntervalTimeKvpField[i].setStringValue(alarmTriggerIntervalTime_UIC[i].getText());
                        } else if (source==alarmSendRemindersEnabled_UIC[i]) {
                            alarmSendReminderEnabledKvpField[i].setStringValue(RciProtocol.toString(alarmSendRemindersEnabled_UIC[i].isSelected()));
                        } else if (source==alarmReminderIntervalTime_UIC[i]) {
                            alarmReminderIntervalTimeKvpField[i].setStringValue(alarmReminderIntervalTime_UIC[i].getText());
                        } else {
                            continue;
                        }
                        break;
                    }
                }
            }
        };

        createViewContent();
    }

    /**
     * Builds the controls on the view. This method builds the view content based
     * upon the capabilities of device we are connected to. If we are not connected to a
     * device, then an empty page is created. This method should be called whenever
     * changing the device this view is connected to because the view content varies
     * per device.
     */
    private void createViewContent()  {
        // Create the panel that will hold the view controls
        content = new GridContentPanel(this.getName(),1);

        if ((device==null) || (modelInfo==null) ) {
            return;
        }

        // Allocate view field and control arrays that are dynamic based on device info
        alarmCount = modelInfo.getAlarmCount();
        alarmEnabledKvpField = new KvpField[alarmCount];
        alarmToKvpField = new KvpField[alarmCount];
        alarmCcKvpField = new KvpField[alarmCount];
        alarmSubjectKvpField = new KvpField[alarmCount];
        alarmPriorityKvpField = new KvpField[alarmCount];
        alarmTriggerModeKvpField = new KvpField[alarmCount];
        alarmPatternKvpField = new KvpField[alarmCount];
        alarmPatternPortKvpField = new KvpField[alarmCount];
        alarmMonitorMaskKvpField = new KvpField[alarmCount];
        alarmStateMaskKvpField = new KvpField[alarmCount];
        alarmTriggerIntervalTimeKvpField = new KvpField[alarmCount];
        alarmSendReminderEnabledKvpField = new KvpField[alarmCount];
        alarmReminderIntervalTimeKvpField = new KvpField[alarmCount];

        alarmEnabled_UIC = new JCheckBox[alarmCount];
        alarmTo_UIC = new JTextField[alarmCount];
        alarmCc_UIC = new JTextField[alarmCount];
        alarmSubject_UIC = new JTextField[alarmCount];
        alarmPriority_UIC = new JComboBox[alarmCount];
        alarmTriggerMode_UIC = new JComboBox[alarmCount];
        alarmPattern_UIC = new JTextField[alarmCount];
        alarmPatternPort_UIC = new JComboBox[alarmCount];
        alarmTrigger_UIC = new BitMaskPanel[alarmCount];
        alarmTriggerIntervalTime_UIC = new JTextField[alarmCount];
        patternOptionsContent = new GridContentPanel[alarmCount];
        gpioOptionsContent = new GridContentPanel[alarmCount];
        alarmSendRemindersEnabled_UIC = new JCheckBox[alarmCount];
        alarmReminderIntervalTime_UIC = new JTextField[alarmCount];

        alarmMonitorMask_UIC = new JTextField[alarmCount];
        alarmStateMask_UIC = new JTextField[alarmCount];

        //int bits[] = new int[modelInfo.getGpioCount()];


        //
        // Create the fields and put them on the view
        //
        alarmsEnabled_UIC = content.addJCheckBox("AlarmsEnabled",fieldListener);

        alarmContent = new GridContentPanel(1);
        alarmContent.addTextLine("AlarmDesc");
        alarmContent.addBlankLine();
        // Add SMTP Server Fields
        alarmContent.addTextLine("SmtpSettings");
        smtpContent = new GridContentPanel(1);
        smtpContent.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        //RegexFormatter ipFormatter = new RegexFormatter("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
        alarmSmtpServer_UIC = smtpContent.addJTextField("AlarmSmtpServer", "AlarmSmtpServerDesc", 150, fieldListener);
        alarmSmtpServer_UIC.setDocument(createNetworkAddressDocument());

        alarmSmtpFrom_UIC = smtpContent.addJTextField("AlarmSmtpFrom", "AlarmSmtpFromDesc", 150, fieldListener);
        alarmSmtpFrom_UIC.setDocument(createEmailDocument());

        alarmContent.addSubPanel(smtpContent);
        alarmContent.addBlankLine();

        // Add Alarm List Panel
        alarmContent.addTextLine("AlarmListDesc");
        detailContent = new GridContentPanel(2);
        detailContent.setBorder(BorderFactory.createLineBorder(Color.BLACK));


        // Create individual alarm controls
        for (int i=0;i<alarmCount; i++) {
            detailContent.addHeadingBar("Alarm #"+(i+1));
            alarmEnabled_UIC[i] = detailContent.addJCheckBox("AlarmEnabled",fieldListener,0,true);

            alarmTo_UIC[i] = detailContent.addJTextField("AlarmTo", "AlarmToDesc", 150, fieldListener, 0, false);
            alarmTo_UIC[i].setDocument(createEmailDocument());
            alarmCc_UIC[i] = detailContent.addJTextField("AlarmCc", "AlarmCcDesc", 150, fieldListener, 1, true);
            alarmCc_UIC[i].setDocument(createEmailDocument());
            alarmSubject_UIC[i] = detailContent.addJTextField("AlarmSubject", "AlarmSubjectDesc", 150, fieldListener, 0, false);
            alarmSubject_UIC[i].setDocument(createGeneralDocument());
            String priorityChoices[] = {"normal", "high"};
            alarmPriority_UIC[i] = detailContent.addJComboBox("AlarmPriority", "AlarmPriorityDesc", priorityChoices, fieldListener, 1, true);

            boolean hasGpio = modelInfo.getGpioCount()>0;
            String triggerModeChoices[] = hasGpio ? new String[] {"gpio", "pattern_match"} : new String[] {"pattern_match"};

            alarmTriggerMode_UIC[i] = detailContent.addJComboBox("AlarmTriggerMode", "AlarmTriggerModeDesc", triggerModeChoices, fieldListener, 0, true);
            patternOptionsContent[i] = new GridContentPanel(2);
            patternOptionsContent[i].setBorder(BorderFactory.createTitledBorder("Pattern Options"));
            detailContent.addSubPanel(patternOptionsContent[i]);
//            alarmPattern_UIC[i] = detailContent.addJTextField("AlarmPattern", "AlarmPatternDesc", 150, fieldListener, 0, false);
            alarmPattern_UIC[i] = patternOptionsContent[i].addJTextField("AlarmPattern", "AlarmPatternDesc", 150, fieldListener, 0, false);
            alarmPattern_UIC[i].setEnabled(false);
            String patternPortChoices[] = new String[modelInfo.getSerialPortCount()];
            for (int p=0;p<modelInfo.getSerialPortCount(); p++) {
                patternPortChoices[p] = Integer.toString(p+1);
            }
//            alarmPatternPort_UIC[i] = detailContent.addJComboBox("AlarmPatternPort", "AlarmPatternPortDesc", patternPortChoices, fieldListener, 1, true);
            alarmPatternPort_UIC[i] = patternOptionsContent[i].addJComboBox("AlarmPatternPort", "AlarmPatternPortDesc", patternPortChoices, fieldListener, 1, true);
            alarmPatternPort_UIC[i].setEnabled(false);


            gpioOptionsContent[i] = new GridContentPanel(2);
            gpioOptionsContent[i].setBorder(BorderFactory.createTitledBorder("Gpio Options"));
            detailContent.addSubPanel(gpioOptionsContent[i]);

            if (hasGpio) {
                alarmTrigger_UIC[i] = new BitMaskPanel("Gpio");
                alarmTrigger_UIC[i].addActionListener(fieldListener);
                gpioOptionsContent[i].addField("AlarmTrigger", alarmTrigger_UIC[i], "AlarmTriggerDesc",0,false);
                gpioOptionsContent[i].addField("AlarmTrigger", alarmTrigger_UIC[i], "AlarmTriggerDesc",0,false);
                alarmTriggerIntervalTime_UIC[i] = gpioOptionsContent[i].addJTextField("AlarmTriggerIntervalTime", "AlarmTriggerIntervalTimeDesc", 150, fieldListener, 1, true);
                alarmTriggerIntervalTime_UIC[i].setDocument(createIntegerDocument());

                alarmSendRemindersEnabled_UIC[i] = gpioOptionsContent[i].addJCheckBox("AlarmSendRemindersEnabled", fieldListener, 0, false); 
                alarmReminderIntervalTime_UIC[i] = gpioOptionsContent[i].addJTextField("AlarmReminderIntervalTime", "AlarmReminderIntervalTimeDesc", 150, fieldListener, 1, true);
                alarmReminderIntervalTime_UIC[i].setDocument(createIntegerDocument());
            }
        }
        JScrollPane scrollPane = new JScrollPane(detailContent);
        scrollPane.setPreferredSize(new Dimension(400,300));
        scrollPane.setOpaque(false);
        scrollPane.getViewport().setOpaque(false);
        scrollPane.getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE);

        alarmContent.addSubPanel(scrollPane);

        content.addSubPanel(alarmContent);

        content.addVGlue();
    }

    /**
     * Returns a one word name identifying this view. 
     */
    public String getName() {
        return "AlarmGpioView";
    }

    /** 
     * Return the Component that displays the primary content for this view
     */
    public Component getViewContent() {
        return content;
    }



    /**
     * Informs view what device to work with. View should flush any
     * cached device data and mark current view content as invalid
     * so that it is refreshed appropriatly.
     */
    public void setDevice(Device device) {
        super.setDevice(device);
        modelInfo = device.getDeviceModelInfo();
        createViewContent();
        refreshViewData();
        refreshViewControls();
        device.addSettingChangeListener(settingChangeListener);
    }


    /** 
     * Refreshes the local copy of the kvpGroup displayed in the view. The updated kvpGroup come
     * from those currently cached in the Device
     */
    private void refreshViewData() {
        viewSettingTree.clear();

        // Get all the alarm settings
        KvpNode alarmSettings = viewSettingTree.mergeChild(device.getInternalSettingTree().getChild("gpio_alarm"),true);
        if (alarmSettings!=null) {
            // Point fields references at data used in views
            alarmsEnabledKvpField   = alarmSettings.getChild("state");
            alarmSmtpServerKvpField = alarmSettings.getChild("smtp_server");
            alarmSmtpFromKvpField   = alarmSettings.getChild("from");


            for (int i=0;i<alarmCount; i++) {
                KvpNode anAlarm = alarmSettings.getChild("alarm", i+1);
                alarmEnabledKvpField[i] = anAlarm.getChild("state");
                alarmToKvpField[i] = anAlarm.getChild("to");
                alarmCcKvpField[i] = anAlarm.getChild("cc");
                alarmSubjectKvpField[i] = anAlarm.getChild("subject");
                alarmPriorityKvpField[i] = anAlarm.getChild("priority");
                alarmTriggerModeKvpField[i] = anAlarm.getChild("trigger_mode");
                alarmPatternKvpField[i] = anAlarm.getChild("match_string");
                alarmPatternPortKvpField[i] = anAlarm.getChild("port");
                alarmMonitorMaskKvpField[i] = anAlarm.getChild("monitor_mask");
                alarmStateMaskKvpField[i] = anAlarm.getChild("state_mask");
                alarmTriggerIntervalTimeKvpField[i] = anAlarm.getChild("alarm_throttle");
                alarmSendReminderEnabledKvpField[i] = anAlarm.getChild("trigger_on_state");
                alarmReminderIntervalTimeKvpField[i] = anAlarm.getChild("alarm_interval");
            }
        }
    }

    /** 
     * Refreshes the state of the controls in the view to match the data in the views kvpGroup.
     */
    private void refreshViewControls() {
        // assume panel is enabled at this point
        content.setContainerEnabled(true);

        alarmSmtpServer_UIC.setEnabled(alarmSmtpServerKvpField!=null);
        if (alarmSmtpServerKvpField!=null) {
            alarmSmtpServer_UIC.setText(alarmSmtpServerKvpField.getStringValue());
        }
        alarmSmtpFrom_UIC.setEnabled(alarmSmtpFromKvpField!=null);
        if (alarmSmtpFromKvpField!=null) {
            alarmSmtpFrom_UIC.setText(alarmSmtpFromKvpField.getStringValue());
        }

        for (int i=0;i<alarmCount; i++) {
            alarmEnabled_UIC[i].setEnabled(alarmEnabledKvpField[i]!=null);
            if (alarmEnabledKvpField[i]!=null) {
                alarmEnabled_UIC[i].setSelected(RciProtocol.booleanValue(alarmEnabledKvpField[i].getStringValue()));
            }

            alarmTo_UIC[i].setEnabled(alarmToKvpField[i]!=null);
            if (alarmToKvpField[i]!=null) {
                alarmTo_UIC[i].setText(alarmToKvpField[i].getStringValue());
            }
            alarmCc_UIC[i].setEnabled(alarmCcKvpField[i]!=null);
            if (alarmCcKvpField[i]!=null) {
                alarmCc_UIC[i].setText(alarmCcKvpField[i].getStringValue());
            }
            alarmSubject_UIC[i].setEnabled(alarmSubjectKvpField[i]!=null);
            if (alarmSubjectKvpField[i]!=null) {
                alarmSubject_UIC[i].setText(alarmSubjectKvpField[i].getStringValue());
            }
            alarmPriority_UIC[i].setEnabled(alarmPriorityKvpField[i]!=null);
            if (alarmPriorityKvpField[i]!=null) {
                alarmPriority_UIC[i].setSelectedItem(alarmPriorityKvpField[i].getStringValue());
            }

            alarmTriggerMode_UIC[i].setEnabled(alarmTriggerModeKvpField[i]!=null);
            if (alarmTriggerModeKvpField[i]!=null) {
                alarmTriggerMode_UIC[i].setSelectedItem(alarmTriggerModeKvpField[i].getStringValue());
            }
            alarmPattern_UIC[i].setEnabled(alarmPatternKvpField[i]!=null);
            if (alarmPatternKvpField[i]!=null) {
                alarmPattern_UIC[i].setText(alarmPatternKvpField[i].getStringValue());
            }
            alarmPatternPort_UIC[i].setEnabled(alarmPatternPortKvpField[i]!=null);
            if (alarmPatternPortKvpField[i]!=null) {
                alarmPatternPort_UIC[i].setSelectedItem(alarmPatternPortKvpField[i].getStringValue());
            }
            boolean hasGpio = modelInfo.getGpioCount()>0;
            if (hasGpio) {
                // determine trigger bits
                alarmTrigger_UIC[i].setEnabled((alarmMonitorMaskKvpField[i]!=null) && (alarmStateMaskKvpField[i]!=null));
                if ((alarmMonitorMaskKvpField[i]!=null) && (alarmStateMaskKvpField[i]!=null)) {
                    int bits[] = computeTriggerBits(alarmMonitorMaskKvpField[i].getStringValue(), alarmStateMaskKvpField[i].getStringValue());
                    alarmTrigger_UIC[i].setBits(bits);
                }
                alarmTriggerIntervalTime_UIC[i].setEnabled(alarmTriggerIntervalTimeKvpField[i]!=null);
                if (alarmTriggerIntervalTimeKvpField[i]!=null) {
                    alarmTriggerIntervalTime_UIC[i].setText(alarmTriggerIntervalTimeKvpField[i].getStringValue());
                }
                alarmSendRemindersEnabled_UIC[i].setEnabled(alarmSendReminderEnabledKvpField[i]!=null);
                if (alarmSendReminderEnabledKvpField[i]!=null) {
                    alarmSendRemindersEnabled_UIC[i].setSelected(RciProtocol.booleanValue(alarmSendReminderEnabledKvpField[i].getStringValue()));
                }
                alarmReminderIntervalTime_UIC[i].setEnabled(alarmReminderIntervalTimeKvpField[i]!=null);
                if (alarmReminderIntervalTimeKvpField[i]!=null) {
                    alarmReminderIntervalTime_UIC[i].setText(alarmReminderIntervalTimeKvpField[i].getStringValue());
                }
            }
            

            boolean gpio_selected = true;
            String triggerMode = alarmTriggerMode_UIC[i].getSelectedItem().toString();
            if (triggerMode.equalsIgnoreCase("gpio"))
                gpio_selected = true;
            else if (triggerMode.equalsIgnoreCase("pattern_match"))
                gpio_selected = false;

            patternOptionsContent[i].setVisible(!gpio_selected);
            gpioOptionsContent[i].setVisible(gpio_selected);

            alarmPattern_UIC[i].setEnabled(!gpio_selected);
            alarmPatternPort_UIC[i].setEnabled(!gpio_selected);
            if (hasGpio) {
                alarmTrigger_UIC[i].setEnabled(gpio_selected);
                alarmTriggerIntervalTime_UIC[i].setEnabled(gpio_selected);
                alarmSendRemindersEnabled_UIC[i].setEnabled(gpio_selected);
                alarmReminderIntervalTime_UIC[i].setEnabled(gpio_selected);
            }
        }


        alarmsEnabled_UIC.setEnabled(alarmsEnabledKvpField!=null);
        if (alarmsEnabledKvpField!=null) {
            alarmsEnabled_UIC.setSelected(RciProtocol.booleanValue(alarmsEnabledKvpField.getStringValue()));
            if (!RciProtocol.booleanValue(alarmsEnabledKvpField.getStringValue())) {
                alarmContent.setContainerEnabled(false);
            }
        }
        // If no device data is not available, disable the entire panel
        if (this.alarmsEnabledKvpField==null) {
            content.setContainerEnabled(false);
        }
    }


    /**
     * Computes the gpio trigger bits based on the vaues of the monitor mask and state mask.
     * This method understands the bit layout of the gpio mask and maps it into a simple
     * array of bits with values of 0, 1, or 2. The have the following meaning:
     *   0 - don't care
     *   1 - asserted
     *   2 - deasserted
     */
    protected int[] computeTriggerBits(String monitorMaskValue, String stateMaskValue) {
        if (modelInfo==null) {
            return null;
        }
        int pins[] = new int[modelInfo.getGpioCount()];
        // get the mask values
        int monitorMask = 0;
        int stateMask = 0;
        if ((monitorMaskValue!=null) && monitorMaskValue.length()>0) {
            try {
                monitorMask = Integer.parseInt(monitorMaskValue.substring(2), 16);
            } catch (NumberFormatException e) {
                SystemLog.log("GeneralException",e);
            }
        }
        if ((stateMaskValue!=null) && stateMaskValue.length()>0) {
            try {
                stateMask =  Integer.parseInt(stateMaskValue.substring(2), 16);
            } catch (NumberFormatException e) {
                SystemLog.log("GeneralException",e);
            }
        }

        // Walk each trigger bit and set its state
        for (int pin=0; pin<pins.length; pin++) {
            int pinMask = modelInfo.getAlarmGpioPinMask(pin);
            int pinState=0; // initially assume its a don't care state
            if ((monitorMask & pinMask)!=0) {
                // If the pin is ON in the monitor mask then look at the state mask to see what its state is
                if ((stateMask & pinMask)!=0) {
                    pinState = 1; // pin is in the Asserted State
                } else {
                    pinState = 2; // pin is in the UnAsserted State
                }
            }
            // Assign the state to the pin bits
            pins[pin] = pinState;
            //SystemLog.debug("Pin bit["+pin+"] is: "+pinState);
        }
        return pins;
    }

    /**
     * Compute the gpio monitor mask from a given set of gpioTriggerBits
     */
    protected String computeMonitorMask(int gpioTriggerBits[]) {
        int monitorMask = 0;
        for (int pin=0; pin<gpioTriggerBits.length; pin++) {
            if (gpioTriggerBits[pin]>0) {
                // If this pin is not in the DONT_CARE state the set the appropriate monitor mask bit
                monitorMask |= modelInfo.getAlarmGpioPinMask(pin);
            }
        }
        String finalMask = "0x"+Integer.toHexString(monitorMask);
        SystemLog.debug("computed monitor mask as: "+finalMask);
        return finalMask;
    }

    /**
     * Compute the gpio state mask from a given set of gpioTriggerBits
     */
    protected String computeStateMask(int gpioTriggerBits[]) {
        int stateMask = 0;
        for (int pin=0; pin<gpioTriggerBits.length; pin++) {
            if (gpioTriggerBits[pin]>0) {
                // If this pin is not in the DONT_CARE state the set the appropraite state mask bit accordingly
                if (gpioTriggerBits[pin]==1) {
                    // This pin is marked ASSERTED ... turn on the appropriate state mask bit
                    stateMask |= modelInfo.getAlarmGpioPinMask(pin);
                } else {
                    // This pin is marked DEASSERTED ... turn off the appropriate state mask bit
                    // (of course its already off by default so we don't need to do anything)
                }
            }
        }
        String finalMask = "0x"+Integer.toHexString(stateMask);
        SystemLog.debug("computed state mask as: "+finalMask);
        return finalMask;
    }



    /**
     * This method is called to instruct the view that it is about to be made
     * active. When a view is active it needs to make sure its content is correct.
     * An example of why a panel may be inactive is if it were on a tabbed pane 
     * and was not currently visible or if the user selected some other view.
     */
    public void activate() {
        SystemLog.debug("Activating "+getName());
    }

    /**
     * This method is called to instruct the view that it is about to be made
     * inactive. When a view is inactive, it does not need to worry
     * about maintaining its content in a correct state. An example of why a panel
     * may be inactive is if it were on a tabbed pane and was not currently visible
     * or if the user selected some other view.
     */
    public void deactivate() {
        SystemLog.debug("Deactivating "+getName());
    }

    /**
     * Indicates if any changes have been made by the user that have not yet been
     * saved to the device(ie committed).
     */
    public boolean isChanged() {
        return viewSettingTree.hasChanged();
    }

    /**
     * This method instructs the view to validate any of the changes the user has made
     * within the view. Any errors are to be added to the provided errorList. 
     * 
     * @param errorList is a collection of ViewValidationError objects
     */
    public void validateChanges(Collection errorList) {
        /* Here is an example of how to create the validation error. Remember to put the msgId in the MsgResourcebundle.properties
        if (fieldXXValue is invalid) {
           errorList.add(new ValidationError("FieldXXValidationError", new Serializable[] {fieldXXValue})); 
        }
        */

        // If no Alarms, No Validation
        if (!alarmsEnabled_UIC.isSelected()) return;

        try {

            // Validate Server/From
            if (!ValidationHelper.isValidIPAddress(alarmSmtpServer_UIC.getText()) ||
                InetAddress.getByName(alarmSmtpServer_UIC.getText()).equals(InetAddress.getByName("0.0.0.0")))
                errorList.add(new ValidationError("AlarmSmtpServerError"));
            if (!ValidationHelper.isValidEmailAddress(alarmSmtpFrom_UIC.getText()))
                errorList.add(new ValidationError("AlarmSmtpFromError"));

            // Validate Each Alarm
            for (int i = 0; i < alarmCount; i++) {
                if (!ValidationHelper.isValidInteger(alarmTriggerIntervalTime_UIC[i].getText()))
                    errorList.add(new ValidationError("AlarmTriggerIntervalError", new Serializable[]{ String.valueOf(i+1)}));
                if ((alarmTo_UIC[i].getText().length() > 0) &&
                    (!ValidationHelper.isValidEmailAddress(alarmTo_UIC[i].getText())))
                    errorList.add(new ValidationError("AlarmToError", new Serializable[]{ String.valueOf(i+1)}));
                if ((alarmCc_UIC[i].getText().length() > 0) &&
                    (!ValidationHelper.isValidEmailAddress(alarmCc_UIC[i].getText())))
                    errorList.add(new ValidationError("AlarmCcError", new Serializable[]{ String.valueOf(i+1)}));

                if (alarmEnabled_UIC[i].isSelected()) {
                    if (alarmTo_UIC[i].getText().length() == 0)
                        errorList.add(new ValidationError("AlarmToError", new Serializable[]{ String.valueOf(i+1)}));
                    if (alarmSubject_UIC[i].getText().length() == 0)
                        errorList.add(new ValidationError("AlarmSubjectError", new Serializable[]{ String.valueOf(i+1)}));
                }
            }
        } catch (Exception e) {
            System.out.println("Caught Exception in AlarmGpioView::validationChanges()");
            e.printStackTrace();
        }
    }

    /**
     * This method instructs the view to place any changes the user has made within 
     * the view into the provided clusters. Once the changes have been saved to
     * to the device, a subsequent call to commitChanges() will be made.
     */
    public void getChanges(KvpNode settingCluster, KvpNode stateCluster) {
        // Merge the view changes into the provided cluster
        settingCluster.merge(viewSettingTree, false);
    }

    /**
     * Instructs the view to consider any user changes within the view as 
     * saved to the device (ie committed).
     */
    public void commitChanges() {
        // simply reset flags indicating user changes in the contols
        viewSettingTree.resetChanged();
    }

    /** 
     * Instructs the view to discard any changes the user has made within the
     * view and revert those fields to the original state. The view is also 
     * free to refresh all its fields to the present cached state of the device at 
     * this time.
     */
    public void cancelChanges() {
        refreshViewData();
        refreshViewControls();
    }


}

