/*
 * NetworkBasicView.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.text.*;
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 basic network
 * informational panel for the ConnectMe device
 * 
 * This view can be embedded in other panels as desired.
 */


public class NetworkBasicView extends ConfigViewImpl {
    /** A KvpNode that holds just the kvpGroup used in this view */
    KvpNode viewSettingTree;
    /** listens to the device for changes to kvpGroup */
    DeviceChangeListener settingChangeListener;
    /** Panel that holds the view content */
    GridContentPanel content;
    /** Subpanel holding the manual ip assignment content */
    GridContentPanel manualContent;

    // Data Fields currently used in this view
    KvpField ipAssignStaticKvpField;
    KvpField ipAssignDhcpKvpField;
    KvpField ipAssignAutoipKvpField;  // to make it simple for user, we simply mirror this flag to the Dhcp field value
    KvpField ipAddressKvpField;
    KvpField subnetMaskKvpField;
    KvpField gatewayKvpField;
    KvpField nameServerKvpField;
    KvpField domainKvpField;
    KvpField hostNameKvpField;

    // UI Controls for each field
    JRadioButton ipAssignDhcp_UIC;
    JRadioButton ipAssignManual_UIC;
    JTextField   ipAddress_UIC;
    JTextField   subnetMask_UIC;
    JTextField   gateway_UIC;
    JTextField   nameServer_UIC;
    JTextField   domain_UIC;
    JTextField   hostName_UIC;

    /**
     * Constructor. Sets up the view controls
     */
    public NetworkBasicView() throws Exception {
        // create the KvpNode and the kvpGroup change listener
        viewSettingTree = new KvpNode();
        settingChangeListener = new DeviceChangeListener() {
            public void deviceChanged(DeviceChangeEvent e) {
                //SystemLog.debug("NetworkBasicView was notified that device kvpGroup changed");
                refreshViewData();
                refreshViewControls();
            }
        };
        // Create the panel that will hold the view controls
        content = new GridContentPanel(this.getName(),1);
        // create a listener that will detect when a user edits the field values
        ControlChangeAdapter fieldListener = new ControlChangeAdapter() {
            public void changePerformed(Object source, ActionEvent ae, FocusEvent fe) {
                //SystemLog.debug("NetworkBasicView was notified that field "+source.toString()+" changed.");
                if ((source==ipAssignDhcp_UIC) || (source==ipAssignManual_UIC)) {
                    ipAssignStaticKvpField.setStringValue(RciProtocol.toString(!ipAssignDhcp_UIC.isSelected()));
                    ipAssignDhcpKvpField.setStringValue(RciProtocol.toString(ipAssignDhcp_UIC.isSelected()));
                    ipAssignAutoipKvpField.setStringValue(RciProtocol.toString(ipAssignDhcp_UIC.isSelected()));
                    manualContent.setContainerEnabled(!ipAssignDhcp_UIC.isSelected());
                } else if (source==ipAddress_UIC) {
                    ipAddressKvpField.setStringValue(ipAddress_UIC.getText());
                } else if (source==subnetMask_UIC) {
                    subnetMaskKvpField.setStringValue(subnetMask_UIC.getText());
                } else if (source==gateway_UIC) {
                    gatewayKvpField.setStringValue(gateway_UIC.getText());
                } else if (source==nameServer_UIC) {
                    nameServerKvpField.setStringValue(nameServer_UIC.getText());
                } else if (source==domain_UIC) {
                    domainKvpField.setStringValue(domain_UIC.getText());
                } else if (source==hostName_UIC) {
                    hostNameKvpField.setStringValue(hostName_UIC.getText());
                }
            }
        };

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


        content.addTextLine("IPAssignMethod");
        
        ButtonGroup ipAssignGroup = new ButtonGroup();
        ipAssignDhcp_UIC = content.addJRadioButton("IPAssignDhcp", fieldListener);
        ipAssignGroup.add(ipAssignDhcp_UIC);
        ipAssignManual_UIC = content.addJRadioButton("IPAssignManual", fieldListener);
        ipAssignGroup.add(ipAssignManual_UIC);

        // Create the panel that will hold the manual ip assignment controls
        manualContent = new GridContentPanel(1);

        //RegexFormatter ipFormatter = new RegexFormatter("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
        //ipAddress_UIC = manualContent.addJFormattedTextField("IPAddress", "IPAddressDesc", ipFormatter, 100, fieldListener);        
        //subnetMask_UIC = manualContent.addJFormattedTextField("SubnetMask", "SubnetMaskDesc", ipFormatter, 100, fieldListener);
        //gateway_UIC = manualContent.addJFormattedTextField("Gateway", "GatewayDesc", ipFormatter, 100, fieldListener);
        ipAddress_UIC = manualContent.addJTextField("IPAddress", "IPAddressDesc", 100, fieldListener);        
        subnetMask_UIC = manualContent.addJTextField("SubnetMask", "SubnetMaskDesc", 100, fieldListener);
        gateway_UIC = manualContent.addJTextField("Gateway", "GatewayDesc", 100, fieldListener);

        ipAddress_UIC.setDocument(createNetworkAddressDocument());
        subnetMask_UIC.setDocument(createNetworkAddressDocument());
        gateway_UIC.setDocument(createNetworkAddressDocument());

//      dns, domain, & hostname not avail in this release
//        nameServer_UIC = manualContent.addJTextField("NameServer","NameServerDesc",100,fieldListener);
//        domain_UIC = manualContent.addJTextField("Domain","DomainDesc",100,fieldListener);
//        hostName_UIC = manualContent.addJTextField("HostName","HostNameDesc",100,fieldListener);
        content.addSubPanel(manualContent);

        content.addTextLine("IPAssignManualCaveat");
        content.addVGlue();
    }

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

    /** 
     * 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 newDevice) {
        super.setDevice(newDevice);
        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();
        ipAssignStaticKvpField = viewSettingTree.mergeFrom(device.getInternalSettingTree(), "boot", "static"); 
        ipAssignDhcpKvpField = viewSettingTree.mergeFrom(device.getInternalSettingTree(), "boot", "dhcp"); 
        ipAssignAutoipKvpField = viewSettingTree.mergeFrom(device.getInternalSettingTree(), "boot", "autoip"); 
        ipAddressKvpField = viewSettingTree.mergeFrom(device.getInternalSettingTree(), "boot", "ip"); 
        subnetMaskKvpField = viewSettingTree.mergeFrom(device.getInternalSettingTree(), "boot", "subnet"); 
        gatewayKvpField = viewSettingTree.mergeFrom(device.getInternalSettingTree(), "boot", "gateway"); 
        nameServerKvpField = viewSettingTree.mergeFrom(device.getInternalSettingTree(), "boot", "dns"); 
        domainKvpField = viewSettingTree.mergeFrom(device.getInternalSettingTree(), "network", "domain"); 
        hostNameKvpField = viewSettingTree.mergeFrom(device.getInternalSettingTree(), "network", "hostname"); 
    }

    /** 
     * Refreshes the state of the controls in the view to match the data in the views kvpGroup.
     */
    private void refreshViewControls() {
        ipAddress_UIC.setEnabled(ipAddressKvpField!=null);
        if (ipAddressKvpField!=null) {
            ipAddress_UIC.setText(ipAddressKvpField.getStringValue());
        }
        subnetMask_UIC.setEnabled(subnetMaskKvpField!=null);
        if (subnetMaskKvpField!=null) {
            subnetMask_UIC.setText(subnetMaskKvpField.getStringValue());
        }
        gateway_UIC.setEnabled(gatewayKvpField!=null);
        if (gatewayKvpField!=null) {
            gateway_UIC.setText(gatewayKvpField.getStringValue());
        }
// dns, domain, & hostname not avail in this release
//         nameServer_UIC.setEnabled(nameServerKvpField!=null);
//         if (nameServerKvpField!=null) {
//             nameServer_UIC.setText(nameServerKvpField.getStringValue());
//         }
//         domain_UIC.setEnabled(domainKvpField!=null);
//         if (domainKvpField!=null) {
//             domain_UIC.setText(domainKvpField.getStringValue());
//         }
//         hostName_UIC.setEnabled(hostNameKvpField!=null);
//         if (hostNameKvpField!=null) {
//             hostName_UIC.setText(hostNameKvpField.getStringValue());
//         }
        ipAssignDhcp_UIC.setEnabled(ipAssignDhcpKvpField!=null);
        ipAssignManual_UIC.setEnabled(ipAssignDhcpKvpField!=null);
        if (ipAssignDhcpKvpField!=null) {
            boolean dhcpEnabled = RciProtocol.booleanValue(ipAssignDhcpKvpField.getStringValue());
            ipAssignDhcp_UIC.setSelected(dhcpEnabled);
            ipAssignManual_UIC.setSelected(!dhcpEnabled);
            manualContent.setContainerEnabled(!dhcpEnabled);
        }
        // If no device data is not available, disable the entire panel
        if (ipAddressKvpField==null) {
            content.setContainerEnabled(false);
        }

    }

    /**
     * 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) {
        try {
            if (ipAssignDhcp_UIC.isSelected()) return; // Nothing to do
            else if (ipAssignManual_UIC.isSelected()) {
                if (!ValidationHelper.isValidIPAddress(ipAddress_UIC.getText()) ||
                    InetAddress.getByName(ipAddress_UIC.getText()).equals(InetAddress.getByName("0.0.0.0")))
                    errorList.add(new ValidationError("IpAddressValidationError"));
                if (!ValidationHelper.isValidNetworkAddress(subnetMask_UIC.getText()) ||
                    InetAddress.getByName(subnetMask_UIC.getText()).equals(InetAddress.getByName("0.0.0.0")) ||
                    InetAddress.getByName(subnetMask_UIC.getText()).equals(InetAddress.getByName("255.255.255.255")))
                    errorList.add(new ValidationError("SubnetMaskValidationError"));
                if (!ValidationHelper.isValidIPAddress(gateway_UIC.getText()))
                    errorList.add(new ValidationError("GatewayValidationError"));
            }
            else {
                // No Method Selected
                errorList.add(new ValidationError("NetworkAssignValidationError"));
            }
        } catch (Exception e) {
            System.out.println("Caught Exception in NetworkBasicView::validationChanges()");
            e.printStackTrace();
        }
    }

    /**
     * This method instructs the view to place any changes the user has made within 
     * the view into the provided cluster. 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();
    }


}

