/*
 * SerialStatisticsView.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.
 * 
 */

//TODO: Generic grid panel to handle statistics.

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 serial statistics information.
 * 
 * This view can be embedded in other panels as desired.
 */


public class SerialStatisticsView extends ConfigViewImpl {
    /** A KvpNode that holds just the state fields used in this view */
    KvpNode viewStateTree;
    /** listens to the device for changes to state fields */
    DeviceChangeListener stateChangeListener;
    
    GridContentPanel content;
    GridContentPanel signalsContent;
    GridContentPanel countersContent;

    // Counter Data Fields
    KvpField overrunErrKvpField;
    KvpField overflowErrKvpField;
    KvpField frameErrKvpField;
    KvpField parityErrKvpField;
    KvpField rxKvpField;
    KvpField txKvpField;
    // Signal Data Fields
    KvpField dtrKvpField;
    KvpField rtsKvpField;
    KvpField ctsKvpField;
    KvpField dsrKvpField;
    KvpField dcdKvpField;
    KvpField rtsToggleKvpField;

    // Counter UI Controls
    JLabel overrunErr_UIC;
    JLabel overflowErr_UIC;
    JLabel frameErr_UIC;
    JLabel parityErr_UIC;
    JLabel rx_UIC;
    JLabel tx_UIC;
    // Signal UI Controls
    JLabel dtr_UIC;
    JLabel rts_UIC;
    JLabel cts_UIC;
    JLabel dsr_UIC;
    JLabel dcd_UIC;
    JLabel rtsToggle_UIC;


    /**
     * Basic constructor. Sets up the tree view and the edit panel.
     */
    public SerialStatisticsView() throws Exception {
        super(false);
        setIncludeStateFields(true);
        setIncludeSettingsFields(false);

        // create the KvpNode and the change listener
        viewStateTree = new KvpNode();
        stateChangeListener = new DeviceChangeListener() {
            public void deviceChanged(DeviceChangeEvent e) {
                refreshViewData();
                refreshViewControls();
            }
        };
        
        // Create the panel that will hold the view controls
        content = new GridContentPanel(this.getName(),1);

        //
        // Create the fields and put them on the view
        //

        // Signal UI Controls
        content.addHeadingBar("SerialSignalsHeading");
        signalsContent = new GridContentPanel(5);
        dtr_UIC = signalsContent.addJLabel("DTR", null, 25, 0, false);
        rts_UIC = signalsContent.addJLabel("RTS", null, 25, 1, false);
        cts_UIC = signalsContent.addJLabel("CTS", null, 25, 2, false);
        dsr_UIC = signalsContent.addJLabel("DSR", null, 25, 3, false);
        dcd_UIC = signalsContent.addJLabel("DCD", null, 25, 4, true);
        rtsToggle_UIC = signalsContent.addJLabel("RtsToggle", null, 25);
        content.addSubPanel(signalsContent);
        

        // Counter UI Controls
        content.addHeadingBar("SerialStatisticsHeading");
        countersContent = new GridContentPanel(2);
        tx_UIC = countersContent.addJLabel("TX", null, 100, 0, false);
        rx_UIC = countersContent.addJLabel("RX", null, 100, 1, true);
        overrunErr_UIC = countersContent.addJLabel("OverrunErr", null, 100, 0, false);
        overflowErr_UIC = countersContent.addJLabel("OverflowErr", null, 100, 1, true);
        frameErr_UIC = countersContent.addJLabel("FrameErr", null, 100, 0, false);
        parityErr_UIC = countersContent.addJLabel("ParityErr", null, 100, 1, true);
        content.addSubPanel(countersContent);
        
        content.addVGlue();
    }

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

    /** 
     * 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);
        refreshViewData();
        refreshViewControls();
    }

    /** 
     * 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() {
        viewStateTree.clear();
        // Counters
        overrunErrKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "overrun_err"); 
        overflowErrKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "overflow_err"); 
        frameErrKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "frame_err"); 
        parityErrKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "parity_err"); 
        rxKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "rx"); 
        txKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "tx"); 
        // Signals
        dtrKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "dtr"); 
        rtsKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "rts"); 
        ctsKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "cts"); 
        dsrKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "dsr"); 
        dcdKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "dcd"); 
        rtsToggleKvpField = viewStateTree.mergeFrom(device.getInternalStateTree(), "serial_stats", "rts_toggle"); 
    }

    /** 
     * Refreshes the state of the controls in the view to match the data in the views kvpGroup.
     */
    private void refreshViewControls() {
        // Counters
        refreshUIFromField(overrunErr_UIC, overrunErrKvpField);
        refreshUIFromField(overflowErr_UIC, overflowErrKvpField);
        refreshUIFromField(frameErr_UIC, frameErrKvpField);
        refreshUIFromField(parityErr_UIC, parityErrKvpField);
        refreshUIFromField(rx_UIC, rxKvpField);
        refreshUIFromField(tx_UIC, txKvpField);
        // Signals
        refreshUIFromField(dtr_UIC, dtrKvpField);
        refreshUIFromField(rts_UIC, rtsKvpField);
        refreshUIFromField(cts_UIC, ctsKvpField);
        refreshUIFromField(dsr_UIC, dsrKvpField);
        refreshUIFromField(dcd_UIC, dcdKvpField);
        refreshUIFromField(rtsToggle_UIC, rtsToggleKvpField);
    }

    // Helper to set field values and state
    private void refreshUIFromField(JLabel jLabel, KvpField kvpField) {
        jLabel.setEnabled(kvpField!=null);
        if (kvpField!=null) {
            jLabel.setText(kvpField.getStringValue());
        }
    }


    /**
     * 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());
        device.addStateChangeListener(stateChangeListener);
        doRefreshAction();
    }

    /**
     * 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() {
        device.removeStateChangeListener(stateChangeListener);
    }

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

    /**
     * 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) {
        // All fields are readonly
    }

    /**
     * Instructs the view to consider any user changes within the view as 
     * saved to the device (ie committed).
     */
    public void commitChanges() {
        // All fields are readonly
    }

    /** 
     * 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() {
        // All fields are readonly
    }


}

