/*
 * NetworkStatisticsView.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 java.awt.*;
import java.util.*;
import java.io.*;
import java.net.*;




/** 
 * This class is a view panel that shows network statistics.
 * 
 * This view can be embedded in other panels as desired.
 */


public class NetworkStatisticsView 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 ipContent;
    GridContentPanel tcpContent;
    GridContentPanel udpContent;
    GridContentPanel icmpContent;

    // The following field arrays are used to get field values from the device.
    // To get more fields simply add to the appropriate array below.
    // The fields will be layed out automatically on the panel.
    // Add labels for new fields in the resource bundle using the field name
    // and a prefix of "Lbl" (e.g. ipforwardingLbl).

    String ipFields[] = {
        "ipinreceives",
        "ipforwdatagrams",
        "ipforwarding",
        "ipoutnoroutes",
        "iproutingdiscards",
        "ipdefaultttl",
    };

    String tcpFields[] = {
        "tcpinsegs",
        "tcpoutsegs",
        "tcpactiveopens",
        "tcppassiveopens",
        "tcpinerrs",
        "tcpattemptfails",
        "tcpretranssegs",
        "tcpestabresets",
    };
    
    String udpFields[] = {
        "udpindatagrams",
        "udpoutdatagrams",
        "udpinerrors",
        "udpnoports",
    };

    String icmpFields[] = {
        "icmpinmsgs",
        "icmpinerrors",
        "icmpindestunreachs",
    };

    static final int NUM_FIELD_COLUMNS = 2;


    // UI Controls
    JLabel ipLabels[];
    JLabel tcpLabels[];
    JLabel udpLabels[];
    JLabel icmpLabels[];

    /**
     * Basic constructor. Sets up the tree view and the edit panel.
     */
    public NetworkStatisticsView() 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) {
                refreshViewControls();
            }
        
        };
        
        // Create the panel that will hold the view controls
        content = new GridContentPanel(this.getName(),2);

        int fieldColumn = 0;
        boolean endRow = false;

        // IP controls
        content.addHeadingBar("ipStatisticsHeading");
        ipLabels = new JLabel[ipFields.length];
        for (int i=0; i<ipFields.length; ++i) {
            fieldColumn = i % NUM_FIELD_COLUMNS;
            endRow = (fieldColumn == (NUM_FIELD_COLUMNS-1));
            ipLabels[i] = content.addJLabel(ipFields[i] + "Lbl", null, 0, fieldColumn, endRow);
        }

        // TCP controls
        content.addHeadingBar("tcpStatisticsHeading");
        tcpLabels = new JLabel[tcpFields.length];
        for (int i=0; i<tcpFields.length; ++i) {
            fieldColumn = i % NUM_FIELD_COLUMNS;
            endRow = (fieldColumn == (NUM_FIELD_COLUMNS-1));
            tcpLabels[i] = content.addJLabel(tcpFields[i] + "Lbl", null, 0, fieldColumn, endRow);
        }

        // UDP controls
        content.addHeadingBar("udpStatisticsHeading");
        udpLabels = new JLabel[udpFields.length];
        for (int i=0; i<udpFields.length; ++i) {
            fieldColumn = i % NUM_FIELD_COLUMNS;
            endRow = (fieldColumn == (NUM_FIELD_COLUMNS-1));
            udpLabels[i] = content.addJLabel(udpFields[i] + "Lbl", null, 0, fieldColumn, endRow);
        }

        // ICMP controls
        content.addHeadingBar("icmpStatisticsHeading");
        icmpLabels = new JLabel[icmpFields.length];
        for (int i=0; i<icmpFields.length; ++i) {
            fieldColumn = i % NUM_FIELD_COLUMNS;
            endRow = (fieldColumn == (NUM_FIELD_COLUMNS-1));
            icmpLabels[i] = content.addJLabel(icmpFields[i] + "Lbl", null, 0, fieldColumn, endRow);
        }
        
        content.addVGlue();
    }

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

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

    /** 
     * Refreshes the state of the controls in the view to match the data in the views kvpGroup.
     */
    private void refreshViewControls() {
        viewStateTree.clear();

        KvpField field;

        // IP fields
        for (int i=0; i<ipFields.length; ++i) {
            field = viewStateTree.mergeFrom(device.getInternalStateTree(), "net_stats", ipFields[i]);
            refreshUIFromField(ipLabels[i], field);
        }
        
        // TCP fields
        for (int i=0; i<tcpFields.length; ++i) {
            field = viewStateTree.mergeFrom(device.getInternalStateTree(), "net_stats", tcpFields[i]);
            refreshUIFromField(tcpLabels[i], field);
        }

        // UDP fields
        for (int i=0; i<udpFields.length; ++i) {
            field = viewStateTree.mergeFrom(device.getInternalStateTree(), "net_stats", udpFields[i]);
            refreshUIFromField(udpLabels[i], field);
        }

        // ICMP fields
        for (int i=0; i<icmpFields.length; ++i) {
            field = viewStateTree.mergeFrom(device.getInternalStateTree(), "net_stats", icmpFields[i]);
            refreshUIFromField(icmpLabels[i], field);
        }
    }

    // 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
    }
}

