/** BEGIN COPYRIGHT BLOCK
 * Copyright (C) 2001 Sun Microsystems, Inc.  Used by permission.
 * Copyright (C) 2005 Red Hat, Inc.
 * All rights reserved.
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; version 2
 * of the License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 
 * END COPYRIGHT BLOCK **/
package com.netscape.management.admserv.panel;

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import com.netscape.management.client.util.*;
import com.netscape.management.client.console.ConsoleInfo;
import com.netscape.management.admserv.config.*;
import com.netscape.management.nmclf.SuiConstants;

/**
 *
 * @version 0.1 11/23/97
 * @author miodrag@netscape.com
 */
public class NetworkConfigPanel extends PluginConfigPanel implements SuiConstants {

    IConfigDataModel _configData;
    private boolean _unixServer;

    static ResourceSet _resource;
    static String _i18nProcessGroupbox, _i18nIPAddr, _i18nHost,
    _i18nPort, _i18nServerUID, _i18nMsgBadPortFormat;
    static String _i18nConnectGroupbox, _i18nHostNameFilter,
    _i18nIPAddrFilter, _i18nEditHostDialog, _i18nEditIPAddrDialog;
    static String _i18nMsgEnterHost, _i18nMsgCanUseWildcards,
    _i18nMsgEnterIPAddr, _i18nHostFormat, _i18nIPAddrFormat,
    _i18nAddHostDialog, _i18nAddIPAddrDialog;
    static String _i18nPortRange;
    static String _i18nFilterChoice, _i18nIPAddressToolTip, _i18nPortToolTip, _i18nUIDToolTip;
    static String _i18nHostListToolTip, _i18nIPListToolTip;

    static {
        _resource = new ResourceSet("com.netscape.management.admserv.panel.panel");
        _i18nProcessGroupbox = _resource.getString("network","ProcessGroupbox");
        _i18nPort = _resource.getString("network","Port");
        _i18nHost = _resource.getString("network","Host");
        _i18nIPAddr = _resource.getString("network","IPAddr");
        _i18nMsgCanUseWildcards = _resource.getString("network","MsgCanUseWildcards");
        _i18nServerUID = _resource.getString("network","ServerUID");
        _i18nMsgBadPortFormat = _resource.getString("network","MsgBadPortFormat");
        _i18nConnectGroupbox = _resource.getString("network","ConnectGroupbox");
        _i18nHostNameFilter = _resource.getString("network","HostNameFilter");
        _i18nIPAddrFilter = _resource.getString("network","IPAddrFilter");
        _i18nEditHostDialog = _resource.getString("network","EditHostDialog");
        _i18nEditIPAddrDialog = _resource.getString("network","EditIPAddrDialog");
        _i18nMsgEnterHost = _resource.getString("network","MsgEnterHost");
        _i18nMsgEnterIPAddr = _resource.getString("network","MsgEnterIPAddr");
        _i18nHostFormat = _resource.getString("network","HostFormat");
        _i18nIPAddrFormat = _resource.getString("network","IPAddrFormat");
        _i18nAddHostDialog = _resource.getString("network", "AddHostDialog");
        _i18nAddIPAddrDialog = _resource.getString("network", "AddIPAddrDialog");
        _i18nPortRange = _resource.getString("common","PortRange");
        _i18nFilterChoice = _resource.getString("network","ToolTipFilterChoice");
        _i18nIPAddressToolTip = _resource.getString("network","IPAddressToolTip");
        _i18nPortToolTip = _resource.getString("network","PortToolTip");
        _i18nUIDToolTip = _resource.getString("network","serverUIDToolTip");
        _i18nHostListToolTip = _resource.getString("network","HostListToolTip");
        _i18nIPListToolTip = _resource.getString("network","IPListToolTip");

    }

    Help _help;

    // Panel Controls
    JLabel _lblPort, _lblAddress, _lblServerUID;
    JTextField _txtPort, _txtAddress, _txtServerUID;
    FilterEditList _hostList, _ipList;

    public NetworkConfigPanel(String title, IConfigDataModel data,
            boolean unixServer) {
        super(title);
        _configData = data;
        _unixServer = unixServer;

        setLayout(new BorderLayout());
        add(makeConfigPanel(), BorderLayout.NORTH);
        _help = new Help(_resource);
    }

    public void showHelp() {
        _help.contextHelp("networkHelp");
    }


    public IConfigDataModel getDataModel() {
        return _configData;
    }

    public void setDataModel(IConfigDataModel data) {
        _configData = data;
        if (_configData.isLoaded()) {
            setPanelContent(_configData);
        }
    }

    public void initialize() throws RemoteRequestException {
        if (!_configData.isLoaded())
            _configData.load();

        if (_configData instanceof CGIDataModel) {
            ((CGIDataModel)_configData).setDialogParent(getParent());
        } else if (_configData instanceof CGIAggregateDataModel) {
            ((CGIAggregateDataModel)_configData).setDialogParent(
                    getParent());
        }
        setPanelContent(_configData);
    }

    public void resetContent() {
        setPanelContent(_configData);
    }

    public void applyChanges() throws ValidationException {
        try {
            validateData();
            getPanelContent(_configData);
        } catch (ValidationException e) {
            throw e;
        }
    }

    public void validateData() throws ValidationException {
        try {
            int portNum = Integer.parseInt(_txtPort.getText());
            if (portNum < 1 || portNum > 65535) {
                throw new ValidationException("",_i18nPortRange);
            }
        } catch (Exception e) {
            throw new ValidationException(_i18nPort +
                _txtPort.getText(), _i18nPortRange);
        }
        validateIPAddress(getAddress());
    }

    public void registerEditComponents(EditMonitor editMonitor) {
        editMonitor.monitor(_txtPort);
        editMonitor.monitor(_txtAddress);
        if (_unixServer) {
            editMonitor.monitor(_txtServerUID);
        }
        _hostList.addListDataListener(editMonitor);
        _ipList.addListDataListener(editMonitor);
    }

    public void validateIPAddress(String ipAddr)
            throws ValidationException {
        if (ipAddr.length() == 0) {
            return; // no ip address means listen on all interfaces
        }

        StringTokenizer checker = new StringTokenizer(ipAddr, ".");
        if (checker.countTokens() != 4 || ipAddr.startsWith(".") ||
                ipAddr.endsWith(".")) {
            throw new ValidationException("",
                    NetworkConfigPanel._i18nMsgEnterIPAddr);
        }
        while (checker.hasMoreElements()) {
            String ipAddrComponent = (String) checker.nextElement();
            try {
                //parseInt will throw exception if bad numner format
                int i = Integer.parseInt(ipAddrComponent);
            } catch (Exception e) {
                throw new ValidationException("",
                        NetworkConfigPanel._i18nMsgEnterIPAddr);
            }
        }
    }

    public void setPanelContent(IConfigDataModel data) {
        String port = data.getAttribute(AttrNames.CONFIG_SERVERPORT);
        setPort(port);
        _lblPort.setText(_i18nPort);
        _txtPort.setEnabled(true);

        String address = data.getAttribute(AttrNames.CONFIG_SERVERADDRESS);
        setAddress(address);
        _lblAddress.setText(_i18nIPAddr);
        _txtAddress.setEnabled(true);

        if (_unixServer) {
            setServerUID(data.getAttribute(AttrNames.CONFIG_USER));
        }

        _hostList.setList( CGIServerSetup.parseFilterList(
                (String) data.getAttribute(AttrNames.CONFIG_HOSTS)));
        _ipList.setList( CGIServerSetup.parseFilterList(
                (String) data.getAttribute(AttrNames.CONFIG_ADDRESSES)));
    }

    public void getPanelContent(IConfigDataModel data)
            throws ValidationException {
        try {
            data.setAttribute(AttrNames.CONFIG_SERVERPORT,
                    _txtPort.getText());

            data.setAttribute(AttrNames.CONFIG_SERVERADDRESS,
                    getAddress());

            data.setAttribute(AttrNames.CONFIG_HOSTS,
                    CGIServerSetup.encodeFilterList(_hostList.getList()));
            data.setAttribute(AttrNames.CONFIG_ADDRESSES,
                    CGIServerSetup.encodeFilterList(_ipList.getList()));
            if (_unixServer) {
                data.setAttribute(AttrNames.CONFIG_USER, getServerUID());
            }
        } catch (ValidationException e) {
            throw e;
        }
    }

    /**
      * Override BaseEditPanel.makeConfigPanel() to provide a custom panel,
      * called by baseEditPanel constructor
     */
    protected JComponent makeConfigPanel() {
        JPanel p = new JPanel();
        GBC gbc = new GBC();
        GridBagLayout gbl;
        JPanel ctrlGroup;

        p.setLayout(gbl = new GridBagLayout());

        gbc.setInsets(0, 0, 0, 0);
        gbc.setGrid(0, 0, 1, 1);
        gbc.setSpace(1.0, 0.0, GBC.WEST, //anchor
                GBC.HORIZONTAL); //fill
        p.add(createProcessGroup(), gbc);

        gbc.setInsets(SEPARATED_COMPONENT_SPACE, 0, 0, 0);
        gbc.setGrid(0, 1, 1, 1);
        gbc.setSpace(1.0, 1.0, GBC.WEST, //anchor
                GBC.BOTH); //fill
        p.add(createConnectGroup(), gbc);

        return p;
    }

    private JPanel createProcessGroup() {
        GridBagLayout gbl;
        GBC gbc = new GBC();
        JPanel group = new JPanel(gbl = new GridBagLayout());
        group.setBorder(
                BaseConfigPanel.createGroupBorder(_i18nProcessGroupbox));

        _lblPort = new JLabel(_i18nPort);
        gbc.setInsets(0, 0, 0, 0);
        gbc.setGrid(0, 0, 1, 1);
        gbc.setSpace(0.0, 0.0, GBC.EAST, //anchor
                GBC.NONE); //fill
        group.add(_lblPort, gbc);

        _txtPort = new JTextField(6);
        _txtPort.setDocument(FilteredInputDocument.allowDigitsOnly());
        gbc.setInsets(0, DIFFERENT_COMPONENT_SPACE, 0, 0);
        gbc.setGrid(1, 0, 1, 1);
        gbc.setSpace(0.0, 0.0, GBC.WEST, // anchor
                GBC.HORIZONTAL); //fill
        group.add(_txtPort, gbc);
        _lblPort.setLabelFor(_txtPort);
        _lblPort.setToolTipText(_i18nPortToolTip);
        _txtPort.setToolTipText(_i18nPortToolTip);

        JLabel label = new JLabel(""); // spacer
        gbc.setInsets(0, 0, 0, 0);
        gbc.setGrid(2, 0, 1, 1);
        gbc.setSpace(1.0, 0.0, GBC.WEST, // anchor
                GBC.HORIZONTAL); //fill
        group.add(label, gbc);

        _lblAddress = new JLabel(_i18nIPAddr);
        gbc.setInsets(COMPONENT_SPACE, 0, 0, 0);
        gbc.setGrid(0, 1, 1, 1);
        gbc.setSpace(0.0, 0.0, GBC.EAST, // anchor
                GBC.NONE); //fill
        group.add(_lblAddress, gbc);

        _txtAddress = new JTextField(16);
        _txtAddress.setDocument(
                FilteredInputDocument.allowIPAddressOnly());
        gbc.setInsets(COMPONENT_SPACE, DIFFERENT_COMPONENT_SPACE, 0, 0);
        gbc.setGrid(1, 1, 2, 1);
        gbc.setSpace(1.0, 0.0, GBC.WEST, // anchor
                GBC.HORIZONTAL); //fill
        group.add(_txtAddress, gbc);
        _lblAddress.setLabelFor(_txtAddress);
        _lblAddress.setToolTipText(_i18nIPAddressToolTip);
        _txtAddress.setToolTipText(_i18nIPAddressToolTip);

        // Add ServerUID only if UNIX server
        if (!_unixServer)
            return group;

        _lblServerUID = new JLabel(_i18nServerUID);
        gbc.setInsets(COMPONENT_SPACE, 0, 0, 0);
        gbc.setGrid(0, 2, 1, 1);
        gbc.setSpace(0.0, 0.0, GBC.EAST, // anchor
                GBC.NONE); //fill
        group.add(_lblServerUID, gbc);

        _txtServerUID = new JTextField(16);
        gbc.setInsets(COMPONENT_SPACE, DIFFERENT_COMPONENT_SPACE, 0, 0);
        gbc.setGrid(1, 2, 2, 1);
        gbc.setSpace(1.0, 0.0, GBC.WEST, // anchor
                GBC.HORIZONTAL); //fill
        group.add(_txtServerUID, gbc);
        _lblServerUID.setLabelFor(_txtServerUID);
        _lblServerUID.setToolTipText(_i18nUIDToolTip);
        _txtServerUID.setToolTipText(_i18nUIDToolTip);

        return group;
    }

    JComboBox _filterChoice;
    JPanel _filterList;
    ActionListener _filterChoiceListener = new ActionListener () {
                public void actionPerformed(ActionEvent e) {
                    if ((String)_filterChoice.getSelectedItem() ==
                            _i18nHostNameFilter) {
                        _card.show(_filterList, "hostList");
                    } else {
                        _card.show(_filterList, "ipList");
                    }
                }
            };

    CardLayout _card;

    private JPanel createConnectGroup() {
        JPanel p = new JPanel(new BorderLayout());
        p.setBorder(
                BaseConfigPanel.createGroupBorder(_i18nConnectGroupbox));

        _filterChoice = new JComboBox();
        _filterChoice.addItem(_i18nHostNameFilter);
        _filterChoice.addItem(_i18nIPAddrFilter);
        _filterChoice.addActionListener(_filterChoiceListener);
        _filterChoice.setToolTipText(_i18nFilterChoice);
        _filterList = new JPanel(_card = new CardLayout());
        _hostList = new HostEditList();
        _hostList.getAccessibleContext().setAccessibleDescription(_i18nHostListToolTip);
        _hostList.setToolTipText(_i18nHostListToolTip);
        _ipList = new IPAddrEditList();
        _ipList.getAccessibleContext().setAccessibleDescription(_i18nIPListToolTip);
        _ipList.setToolTipText(_i18nIPListToolTip);
        _filterList.add(_hostList, "hostList");
        _filterList.add(_ipList, "ipList");

        JPanel p1 = new JPanel (new BorderLayout());
        p1.add(_filterChoice, BorderLayout.WEST);
        p.add(p1, BorderLayout.NORTH);
        p.add(_filterList, BorderLayout.CENTER);

        return p;
    }


    private JPanel createHostRestrictGroup() {
        JPanel group = new JPanel(new BorderLayout());
        group.add(_hostList = new HostEditList(), BorderLayout.NORTH);
        return group;
    }

    private JPanel createIPRestrictGroup() {
        JPanel group = new JPanel(new BorderLayout());
        group.add(_ipList = new IPAddrEditList(), BorderLayout.NORTH);
        return group;
    }


    public void setPort(String port) {
        _txtPort.setText((port != null) ? port : "");
    }

    public String getPort() {
        String port = _txtPort.getText();
        return port;
    }

    public void setAddress(String addr) {
        _txtAddress.setText((addr != null) ? addr : "");
    }

    public String getAddress() {
        String addr = _txtAddress.getText();
        return addr;
    }


    public void setServerUID(String account) {
        _txtServerUID.setText((account != null) ? account : "");
        if (account != null) {
            _txtServerUID.setEnabled(account.equals("root"));
        }
    }

    public String getServerUID() {
        String account = _txtServerUID.getText();
        return account;
    }
}

/**
  * Host Edit List
  */
class HostEditList extends FilterEditList {

    static String _i18nEditHost, _i18nAddHost, _i18nRemoveHost;
    static {
        _i18nEditHost = _resource.getString("network","EditHostToolTip");
        _i18nAddHost = _resource.getString("network","AddHostToolTip");
        _i18nRemoveHost = _resource.getString("network","RemoveHostToolTip");
    }

    public JPanel getEditPanel() {
        _editPanel = new FilterEditPanel(NetworkConfigPanel._i18nHost,
                NetworkConfigPanel._i18nHostFormat);
        setEditPanelInitalFocusComponent(_editPanel.getTextField());
        setEditPanelCommitOnEnterComponents(
                new JTextField[]{_editPanel.getTextField()});
        return _editPanel;
    }

    public String getEditTitle() {
        return NetworkConfigPanel._i18nEditHostDialog;
    }
    public String getAddTitle() {
        return NetworkConfigPanel._i18nAddHostDialog;
    }

    public String getEditToolTip() {
        return _i18nEditHost;
    }

    public String getAddToolTip() {
        return _i18nAddHost;
    }

    public String getRemoveToolTip() {
        return _i18nRemoveHost;
    }

    public ResourceSet getHelpResourceSet() {
        return NetworkConfigPanel._resource;
    };
    public String getHelpToken() {
        return "editHostHelp";
    }

    public void validateEdit() throws ValidationException {
        String host = _editPanel.getItem();
        if (host.length() == 0) {
            throw new ValidationException("",
                    NetworkConfigPanel._i18nMsgEnterHost);
        } else {
            for (int i = 0; i < host.length(); i++) {
                char c = host.charAt(i);
                if (c > 0x007f) {
                    throw new ValidationException("",
                            NetworkConfigPanel._i18nMsgEnterHost);
                }
            }
        }
    }
}

/**
  * IP Address Edit List
  */
class IPAddrEditList extends FilterEditList {

    static String _i18nEditIP, _i18nAddIP, _i18nRemoveIP;
    static {
        _i18nEditIP = _resource.getString("network","EditIPToolTip");
        _i18nAddIP = _resource.getString("network","AddIPToolTip");
        _i18nRemoveIP = _resource.getString("network","RemoveIPToolTip");
    }

    public JPanel getEditPanel() {
        _editPanel = new FilterEditPanel(NetworkConfigPanel._i18nIPAddr,
                NetworkConfigPanel._i18nIPAddrFormat);
        _editPanel.getTextField().setDocument(
                new FilteredInputDocument("1234567890.*"));
        setEditPanelInitalFocusComponent(_editPanel.getTextField());
        setEditPanelCommitOnEnterComponents(
                new JTextField[]{_editPanel.getTextField()});
        return _editPanel;
    }

    public String getEditTitle() {
        return NetworkConfigPanel._i18nEditIPAddrDialog;
    }
    public String getAddTitle() {
        return NetworkConfigPanel._i18nAddIPAddrDialog;
    }

    public String getEditToolTip() {
        return _i18nEditIP;
    }

    public String getAddToolTip() {
        return _i18nAddIP;
    }

    public String getRemoveToolTip() {
        return _i18nRemoveIP;
    }

    public ResourceSet getHelpResourceSet() {
        return NetworkConfigPanel._resource;
    };
    public String getHelpToken() {
        return "editIPAddrHelp";
    }

    public void validateEdit() throws ValidationException {
        String ipAddr = _editPanel.getItem();
        if (ipAddr.length() == 0) {
            String errmsg = NetworkConfigPanel._i18nMsgEnterIPAddr + "\n" +
                    NetworkConfigPanel._i18nMsgCanUseWildcards;
            throw new ValidationException("", errmsg);
        }

        if (ipAddr.equals("*"))
            return ;

        StringTokenizer checker = new StringTokenizer(ipAddr, ".");
        if (checker.countTokens() != 4 || ipAddr.startsWith(".") ||
                ipAddr.endsWith(".")) {
            String errmsg = NetworkConfigPanel._i18nMsgEnterIPAddr + "\n" +
                    NetworkConfigPanel._i18nMsgCanUseWildcards;
            throw new ValidationException("", errmsg);
        }
        while (checker.hasMoreElements()) {
            String ipAddrComponent = (String) checker.nextElement();
            try {
                if (!ipAddrComponent.equals("*")) {
                    //parseInt will throw exception if bad numner format
                    int i = Integer.parseInt(ipAddrComponent);
                }
            } catch (Exception e) {
                String errmsg = NetworkConfigPanel._i18nMsgEnterIPAddr +
                        "\n" + NetworkConfigPanel._i18nMsgCanUseWildcards;
                throw new ValidationException("", errmsg);
            }
        }
    }
}

/**
  * A custom component that enables element in the list to be edited:
  * add, edit, remove
  * Common class for both Host and Ip Addr edit lists
 */
abstract class FilterEditList extends EditableList {

    FilterEditPanel _editPanel;
    Vector _items;

    public FilterEditList() {
        //setBorder(new EmptyBorder(10,0,0,0));
    }

    private int findItem(String name) {
        for (int i = 0; i < _items.size(); i++) {
            String host = (String)_items.elementAt(i);
            if (host.equals(name)) {
                return i;
            }
        }
        return -1;
    }

    /**
      * No custom panel
     */
    public JPanel getDetailsPanel() {
        return null;
    }
    public String getDetailsTitle() {
        return null;
    }


    /**
      * A method called to populate the contents of edit panel.
      * Paremeter <code>item</code> is null for ADD operation. A
      * non-null string is passed for EDIT operation
     */
    public void setEditPanelParameters(String item) {
        if (item != null) {
            _editPanel.setItem(item);
        } else {
            _editPanel.setItem("");
        }
    }

    /**
      * A method called to craete a new item. The item parameters should
      * be read from the custom edit panel
     */
    public void createItem(String name) {
        _items.addElement(new String(name));
    }


    /**
      * A method called to update an item. The item parameters should
      * be read from the custom edit panel
     */
    public void updateItem(String name, boolean isRenamed) {
        int idx = findItem(name);
        if (idx >= 0) {
            _items.setElementAt(new String(_editPanel.getItem()), idx);
        } else {
            Debug.println("ERROR: Item not found: " + name);
        }
    }

    /**
      * A method called to remove an item.
     */
    public void removeItem(String name) {
        int idx = findItem(name);
        if (idx >= 0) {
            _items.removeElementAt(idx);
        } else {
            Debug.println("ERROR: Not found: " + name);
        }
    }

    /**
      * A method called when an item is selected
     */
    public void selectItem(String item) {}

    /**
      * A method called to read the item from the edit panel
     */
    public String getEditPanelItem() {
        return _editPanel.getItem();
    }

    public void setList(Vector v) {
        super.setList(_items = v);
    }

    public Vector getList() {
        return _items;
    }


}

/**
  * Host Filter Edit Panel
 */
class FilterEditPanel extends JPanel implements SuiConstants {
    String _cmd = "", _item = "";
    JTextField _txtItem;
    String _i18nItemLabel, _i18nItemDescription;

    FilterEditPanel(String itemLabel, String itemDescription) {
        _i18nItemLabel = itemLabel;
        _i18nItemDescription = itemDescription;
        createLayout();
    }

    private JPanel createLayout() {
        GBC gbc = new GBC();
        setLayout(new GridBagLayout());

        //JLabel label = new JLabel(_i18nItemDescription);
        //label.setUI(new com.netscape.page.MultilineLabelUI());
        MultilineLabel label = new MultilineLabel(_i18nItemDescription);
        label.setLineWrap(false);
        gbc.setGrid(0, 0, 2, 1);
        gbc.setSpace(1.0, 0.0, GBC.WEST, //anchor
                GBC.HORIZONTAL); //fill
        add(label, gbc);

        JLabel lblItem = new JLabel(_i18nItemLabel);
        gbc.setInsets(COMPONENT_SPACE, 0, 0, 0);
        gbc.setGrid(0, 1, 1, 1);
        gbc.setSpace(0.0, 0.0, GBC.NORTHWEST, // anchor
                GBC.HORIZONTAL); //fill
        add(lblItem, gbc);

        _txtItem = new JTextField(_item, 16);
        gbc.setInsets(COMPONENT_SPACE, DIFFERENT_COMPONENT_SPACE, 0, 0);
        gbc.setGrid(1, 1, 1, 1);
        gbc.setSpace(1.0, 0.0, GBC.NORTHWEST, //anchor
                GBC.HORIZONTAL); //fill
        add(_txtItem, gbc);
        lblItem.setLabelFor(_txtItem);

        return this;
    }

    public String getItem() {
        return _item = _txtItem.getText();
    }

    public void setItem(String item) {
        _txtItem.setText(_item = item);
    }

    public JTextField getTextField() {
        return _txtItem;
    }
}

